220 likes | 377 Views
Ch06 介面與多重繼承. 物件導向程式設計 (2). 單一繼承 vs 多重繼承 (1/2). Java 的繼承是屬於單一繼承, C++ 的繼承是屬於多重繼承 多重繼承是指:指一個類別能夠繼承多個父類別 在 許多時候 多重繼承 的性質是相當有用。 在 Java , 多重繼承 的性質交給 介面 。. 單一繼承 vs 多重繼承 (2/2). 多重繼承的性質很有用,現實環境中,處處是多重繼承,想想以下情境: 你有一隻手機,它有 PDA 和 GPS 的功能,有一天, ToTo 跟你借 GPS
E N D
Ch06 介面與多重繼承 物件導向程式設計(2)
單一繼承 vs 多重繼承(1/2) • Java的繼承是屬於單一繼承,C++的繼承是屬於多重繼承 • 多重繼承是指:指一個類別能夠繼承多個父類別 • 在許多時候多重繼承的性質是相當有用。 • 在Java,多重繼承的性質交給介面。
單一繼承 vs 多重繼承(2/2) • 多重繼承的性質很有用,現實環境中,處處是多重繼承,想想以下情境: 你有一隻手機,它有PDA和GPS的功能,有一天,ToTo跟你借GPS 如果1:你怕ToTo弄壞了,他的媽媽又不會賠,這時,你可以採用『單一繼承』的說法, “不好意思,我有行動電話” 如果2:你不怕ToTo弄壞,因為他弄壞了,你就可以順理成章的成為他的小童星經紀人,好好利用他大賺一筆;則,你可以採用『多重繼承』的說法, “我有一隻手機,它有GPS的功能,借給你”
動動小手時間(1) • 請繪出上一頁的行動電話的繼承圖
介面(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)
介面也是物件的型別 • 當物件所屬之類別在定義時實作某個介面,則此物件也「屬於」該介面型別的物件。意即,介面也是物件的型別。 • 若某個物件,其所屬之類別沒有實作介面,卻定義了介面宣告的方法時,該物件還是不屬於介面型別。 • 介面是物件的型別,所以介面也可以為陣列的基底型別,而形成異質集合。
介面的多重繼承 • 介面和介面之間也可以有繼承的關係,而且可以有多重繼承的關係 • 不可以有靜態常數的重複繼承。如果不同父介面中定義了同名的常數,則子介面型別的物件不可以使用該常數,以免發生曖昧不明的狀況
範例2:介面的多重繼承(1/3) 實線為繼承(extends),虛線為實作介面(implements)
範例2:介面的多重繼承(2/3) • 請先練習一下功力
class Ch06_02 { public static void main(String [] args) { CCF a = new CCF(); a.m1(); a.m3(); a.m4(); a.m5(); } } abstract class CCE { String name = "CCE"; abstract void m1(); void m2() { System.out.println("我在CCE的m2啦!"); } } interface IIA { String name = "IIA"; void m3(); void m5(); } interface IIB { String name = "IIB"; void m3(); } interface IIC extends IIA, IIB { String name = "IIC"; void m3(); } interface IID { String name = "IID"; void m4(); } class CCF extends CCE implements IIC, IID { String name = "CCF"; void m1() { System.out.println("我在CCF的m1!"); m2(); } public void m3() { System.out.println("我在CCF的m3!"); } public void m4() { System.out.println("我在CCF的m4!"); } public void m5() { System.out.println("我在CCF的m5!"); } }請先練習一下功力 範例2:介面的多重繼承(3/3)
介面vs抽象類別(1/3) • 介面和抽象類別的相似之處: • 不能直接使用介面或抽象類別建立物件 • 介面與抽象類別都可以宣告抽象方法。
介面vs抽象類別(2/3) • 介面(Interface)是在類別繼承架構中定義類別行為,內含常數和方法宣告,但是並沒有實作程式碼,它和抽象類別的差異,如下所示: • 抽象類別的方法可能只有宣告,但是仍然可以擁有一般方法,介面的方法都只有宣告,而且一定沒有實作的程式碼。 • 介面不屬於類別的繼承架構,就算亳無關係的類別也一樣可以實作同一個介面。 • 類別只能繼承一個抽象類別,但是可以同時實作多個介面。
介面vs抽象類別(3/3) • 介面和抽象類別的相異之處: • 介面內的方法皆為public 和abstract 方法。抽象類別的抽象方法存取修飾字不限為 public。 • 介面內的屬性皆預設為public、static及final宣告,必須指定其值。抽象類別中的屬性則沒有限定 • 介面之間可以有多重繼承。抽象類別和其它類別之間只能有單一繼承 • 介面的目的是制訂整組訊息接收器的規格,模擬類別的多重繼承。抽象類別的目的則是制訂部份物件的規格,並制訂部份訊息接收器的規格,為多型做準備
大腦、小手動一動(2) • 請設計兩種類別: • 珍珠奶茶 • 奶茶珍珠 • 兩個物件分屬這兩類別