250 likes | 415 Views
Ch15 視窗程式設計 (2). JAVA 程式語言入門 (2). 大綱. 監聽器介面 ( 參考 Ch 10) 事件轉接類別 ( 參考 Ch 10) 抽象類別 介面 多重繼承. 抽象類別 (1/3). 類別定義中,只要有一個方法(或以上)定義為 抽象方法 (abstract method),則該類別為 抽象類別 (abstract class)。 抽象方法並沒有定義方法的主體(沒有實作) 無法利用抽象類別建立物件。 抽象類別的用處是當作父類別,讓子類別繼承。 子類別必須將父類別中的抽象方法實作出來,才能建立物件。. 抽象類別 (2/3).
E N D
Ch15 視窗程式設計(2) JAVA程式語言入門(2)
大綱 • 監聽器介面(參考Ch 10) • 事件轉接類別(參考Ch 10) • 抽象類別 • 介面 • 多重繼承
抽象類別(1/3) • 類別定義中,只要有一個方法(或以上)定義為抽象方法(abstract method),則該類別為抽象類別(abstract class)。 • 抽象方法並沒有定義方法的主體(沒有實作) • 無法利用抽象類別建立物件。 • 抽象類別的用處是當作父類別,讓子類別繼承。 • 子類別必須將父類別中的抽象方法實作出來,才能建立物件。
抽象類別(2/3) • 抽象類別的定義語法: 修飾字 abstract class 類別名稱 { //屬性宣告 修飾字 abstract 型別 方法名稱(參數列); //其它方法定義 } • 某個類別的主體內,宣告了抽象方法,則該類別必須宣告為抽象類別。 • 抽象類別雖然不能用以建立物件,但是可以當作物件的型別,用來宣告參照變數。 • 抽象類別的子類別若不完全實作抽象方法,則依然是抽象類別。
抽象類別(3/3) • 使用抽象類別的用意,主要是「制定固定的訊息接收管道,但不把焦點放在訊息的處理上」。 • 抽象類別和一般類別一樣,都可以定義建構子,只是不能直接以抽象類別的建構子建立物件。 • 抽象方法的目的就是為了讓子類別實作,所以abstract不能同時和final、static或private一起使用。
單一繼承 vs 多重繼承(1/2) • Java的繼承是屬於單一繼承,C++的繼承是屬於多重繼承 • 多重繼承是指:指一個類別能夠繼承多個父類別 • 在許多時候多重繼承的性質是相當有用。 • 在Java,多重繼承的性質交給介面。
單一繼承 vs 多重繼承(2/2) • 多重繼承的性質很有用,現實環境中,處處是多重繼承,想想以下情境: 你有一隻手機,它有PDA和GPS的功能,有一天,ToTo跟你借GPS 如果1:你怕ToTo弄壞了,他的媽媽又不會賠,這時,你可以採用『單一繼承』的說法, “不好意思,我有行動電話” 如果2:你不怕ToTo弄壞,因為他弄壞了,你就可以順理成章的成為他的小童星經紀人,好好利用他大賺一筆;則,你可以採用『多重繼承』的說法, “我有一隻手機,它有GPS的功能,借給你”
介面(1/2) • 介面中定義的方法就像是飲料販賣機上的按鈕
介面(2/2) • 介面(Interface)是在類別繼承架構中定義類別行為,內含常數和方法宣告,但是並沒有實作程式碼
介面的定義與實作(1/3) • 定義介面的語法: 修飾字 interface 介面名稱 { //靜態常數定義 //抽象方法宣告 } • 介面定義的例子: interface MyInterface { int i=2; //已預設使用public、final、static void m();//已預設使用public、abstract }
介面的定義與實作(2/3) • 實作介面的類別定義語法: 修飾字 class 類別名稱implements 介面名稱 { //包含實作方法的敘述 }
介面的定義與實作(3/3) • 介面多重繼承的語法: interface 子介面 extends 父介面一, 父介面二, ... { //新增的靜態常數及抽象方法 } • 類別實作多個介面的語法: class 類別名稱 implements 介面一, 介面二, ... { //類別主體敘述 }
範例1:宣告與使用介面(1/4) • UML類別圖,如下圖所示:
範例1:宣告與使用介面(2/4) • AreaInterface介面,如下所示: interface AreaInterface { final double PI = 3.1415926; void area(); }
範例1:宣告與使用介面(3/4) • 接著Circle類別可以實作這個介面,如下所示: class Circle extends Shape implements AreaInterface { ……… public void area() { System.out.println("X座標: " + x); System.out.println("Y座標: " + y); System.out.println("圓半徑: " + r); System.out.println("圓面積: " + PI*r*r); } }
abstract class Shape0601 { public double x; public double y; } interface AreaInterface0601 { final double PI = 3.1415926; void area(); } class Circle0601 extends Shape0601 implements AreaInterface0601 { public double r; public Circle0601(double x, double y, double r) { this.x = x; this.y = y; this.r = r; } public void area() { System.out.println("X座標: " + x); System.out.println("Y座標: " + y); System.out.println("圓半徑: " + r); System.out.println("圓面積: " + PI*r*r); } } class Ch06_01 { public static void main(String [] args) { Circle0601 c = new Circle0601(5.0, 5.0, 8.0); c.area(); System.out.println("PI常數: " + AreaInterface0601.PI); System.out.println("PI常數(以物件方式): " + c.PI); } } 範例1:宣告與使用介面(4/4)
MouseListener • import javax.swing.*; //引用Swing套件 • import java.awt.*; • import java.awt.event.*; //引用處理事件的event套件 • public class MouseEX extends JFrame { • JButton clickME = new JButton("請按我!"); //建立元件 • JLabel lbMouse = new JLabel("滑鼠事件訊息"), //建立顯示訊息的標籤 • lbMouseButton = new JLabel("按下按鍵"); • //以匿名類別的方式實作MouseListener介面, • //宣告回應滑鼠事件的監聽器 • MouseListener mlBtn = new MouseListener() { • private int clickCount = 0, //記錄按鈕被按下次數的屬性 • doubleClickCount = 0; //記錄按鈕被按下次數的屬性
//處理按一下滑鼠按鍵動作的方法 • public void mouseClicked(MouseEvent e) { • if(e.getClickCount() == 2) • doubleClickCount++; • ((JButton) e.getSource()).setText("按下一下 : " + • (clickCount++) + "次 | 連按兩次 : " + doubleClickCount + "次"); • } • //處理滑鼠游標進入元件的方法 • public void mouseEntered(MouseEvent e) { • ((JButton) e.getSource()).setText("滑鼠游標進入按鈕範圍"); • } • //處理滑鼠游標離開元件的方法 • public void mouseExited(MouseEvent e) { • ((JButton) e.getSource()).setText("滑鼠游標離開按鈕範圍"); • }
//處理按下滑鼠按鍵動作的方法 • public void mousePressed(MouseEvent e){ • switch(e.getButton()){ //取得滑鼠被按下的按鍵 • case MouseEvent.BUTTON1 : • lbMouseButton.setText("滑鼠左鍵被按下"); • break; • case MouseEvent.BUTTON2 : • lbMouseButton.setText("滑鼠中間鍵被按下"); • break; • case MouseEvent.BUTTON3 : • lbMouseButton.setText("滑鼠右鍵被按下"); • break; • case MouseEvent.NOBUTTON : • lbMouseButton.setText("沒有滑鼠按鍵被按下"); • break; • } • } • //處理放開滑鼠按鍵動作的方法 • //即使不處理事件但仍須定義空的回應方法 • public void mouseReleased(MouseEvent e){ } • };
//以匿名類別的方式實作MouseMotionListener介面, • //宣告回應滑鼠事件的監聽器 • MouseMotionListener mmlFrame = new MouseMotionListener(){ • public void mouseDragged(MouseEvent e){ //滑鼠拖曳 • lbMouse.setText("滑鼠在視窗範圍內 [拖曳] , 游標位置在 ( " • + e.getX() + ", " + e.getY() + " )"); • } • public void mouseMoved(MouseEvent e){ //滑鼠移動 • lbMouse.setText("滑鼠在視窗範圍內 [移動] , 游標位置在 ( " • + e.getX() + ", " + e.getY() + " )"); • } • }; • MouseEX(){ • Box bxBtn = new Box(BoxLayout.X_AXIS); • bxBtn.add(Box.createHorizontalGlue()); • bxBtn.add(clickME); //加入按鈕元件 • bxBtn.add(Box.createHorizontalGlue()); • Container cp = getContentPane(); //取得內容面版 • Box bxLabel = new Box(BoxLayout.Y_AXIS);
bxLabel.add(lbMouse); //將標籤元件加入Box容器 • bxLabel.add(Box.createVerticalStrut(10)); • bxLabel.add(lbMouseButton); • cp.add(bxBtn); //將包含按鈕元件的Box容器加入內容面版 • cp.add(bxLabel, BorderLayout.SOUTH); • //將包含標籤元件的Box容器加入面版 • clickME.addMouseListener(mlBtn); • //註冊由mlBtn監聽clickME元件的滑鼠事件 • addMouseMotionListener(mmlFrame); • //註冊由mmlFrame監聽視窗的滑鼠移動事件 • setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); • setSize(300, 250); • setVisible(true); • } • public static void main(String args[]) { • new MouseEX(); //產生視窗框架物件 • } • }
MouseAdapter • import javax.swing.*; //引用Swing套件 • import java.awt.*; • import java.awt.event.*; //引用處理事件的event套件 • public class AdapterEX extends JFrame{ • JButton clickME = new JButton("請按我!"); //建立元件 • JLabel lbPos = new JLabel("顯示滑鼠相關訊息"); • MouseListener mlFrame = new MouseListener(){ • public void mouseClicked(MouseEvent e){ • lbPos.setText("在 (" + e.getX() + ", " + e.getY() + ") 按下滑鼠"); • } • public void mouseEntered(MouseEvent e){ • lbPos.setText("滑鼠游標進入視窗"); • } • public void mouseExited(MouseEvent e){ • lbPos.setText("滑鼠游標離開視窗"); • }
//即使不處理事件但仍須定義空的回應方法 • public void mousePressed(MouseEvent e){ } • public void mouseReleased(MouseEvent e){ } • }; • //運用匿名內部類別, 以繼承MouseAdaptor的方式定義監聽器類別, 並完成宣告 • MouseAdapter maBtn = new MouseAdapter(){ • int clickCount = 0; //記錄按鈕被按下次數的屬性 • public void mouseClicked(MouseEvent e){ • ((JButton) e.getSource()).setText( • "按鈕被按了" + (clickCount++) + "次"); • } • public void mouseEntered(MouseEvent e){ • ((JButton) e.getSource()).setText("滑鼠游標進入按鈕範圍"); • } • public void mouseExited(MouseEvent e){ • ((JButton) e.getSource()).setText("滑鼠游標離開按鈕範圍"); • } • };
AdapterEX(){ • Container cp = getContentPane(); //取得內容面版 • Box bxBtn = new Box(BoxLayout.X_AXIS); • bxBtn.add(Box.createHorizontalGlue()); • bxBtn.add(clickME); //將元件加入Box容器 • bxBtn.add(Box.createHorizontalGlue()); • cp.add(bxBtn); //將Box容器加入內容面版 • cp.add(lbPos, BorderLayout.SOUTH); • clickME.addMouseListener(maBtn); • //註冊由maBtn監聽clickME元件的滑鼠事件 • addMouseListener(mlFrame); • //註冊由mlFrame監聽視窗的滑鼠事件 • setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); • setSize(200, 150); • setVisible(true); • }
public static void main(String args[]) { • new AdapterEX(); //產生視窗框架物件 • } • }