ch06 介面與多重繼承

46
Ch06 Ch06 抽抽抽抽抽抽抽 抽抽抽抽抽抽抽 物物物物物物物物 (2)

Upload: warren

Post on 04-Jan-2016

67 views

Category:

Documents


0 download

DESCRIPTION

Ch06 介面與多重繼承. 物件導向程式設計 (2). 單一繼承 vs 多重繼承 (1/2). Java 的繼承是屬於單一繼承, C++ 的繼承是屬於多重繼承 多重繼承是指:指一個類別能夠繼承多個父類別 在 許多時候 多重繼承 的性質是相當有用。 在 Java , 多重繼承 的性質交給 介面 。. 單一繼承 vs 多重繼承 (2/2). 多重繼承的性質很有用,現實環境中,處處是多重繼承,想想以下情境: 你有一隻手機,它有 PDA 和 GPS 的功能,有一天, ToTo 跟你借 GPS - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Ch06  介面與多重繼承

Ch06 Ch06 抽象類別和多形抽象類別和多形

物件導向程式設計 (2)

Page 2: Ch06  介面與多重繼承

2

方法的覆蓋方法的覆蓋 (1/4)(1/4)

• 子類別的重新定義物件方法稱為方法的子類別的重新定義物件方法稱為方法的覆覆蓋蓋(( OverridingOverriding )。)。

• 方法覆蓋時,下列各項都必須和父類別定方法覆蓋時,下列各項都必須和父類別定義的方法相同:義的方法相同:– 方法的回傳型別。方法的回傳型別。– 方法名稱。方法名稱。– 形式參數列中的型別及順序。形式參數列中的型別及順序。

• 如果子類別定義的方法和父類別定義的方如果子類別定義的方法和父類別定義的方法同名,但參數不同時,只能算是一種多法同名,但參數不同時,只能算是一種多載載 (overloading)(overloading)

Page 3: Ch06  介面與多重繼承

3

方法的覆蓋方法的覆蓋 (2/4)(2/4)

• 覆蓋的原理:先碰到子類別定義之成員覆蓋的原理:先碰到子類別定義之成員

子類別定義之成員

父類別定義之成員

子類別物件

呼叫方法

Page 4: Ch06  介面與多重繼承

4

方法的覆蓋方法的覆蓋 (3/4)(3/4)

• 方法覆蓋的主要用意是「方法覆蓋的主要用意是「修改原有功能的修改原有功能的實作實作」。」。

• 使用使用 finalfinal 宣告的父類別之物件方法宣告的父類別之物件方法不能不能被覆蓋被覆蓋。。

• 靜態方法靜態方法無法使用覆蓋(沒有覆蓋的特無法使用覆蓋(沒有覆蓋的特性)。性)。

• 覆蓋舊方法時,新定義的方法可以透過 覆蓋舊方法時,新定義的方法可以透過 super super 參照呼叫舊方法。參照呼叫舊方法。

Page 5: Ch06  介面與多重繼承

5

方法的覆蓋方法的覆蓋 (4/4)(4/4)

• 方法覆蓋要注意下列幾點:方法覆蓋要注意下列幾點:– 回傳型別必須相同。回傳型別必須相同。– 不能縮減方法的存取權限不能縮減方法的存取權限– 丟出的例外型別必須相同丟出的例外型別必須相同

• 方法覆蓋時,沒有領域不同的區別,所有方法覆蓋時,沒有領域不同的區別,所有被覆蓋的方法一律打入冷宮。被覆蓋的方法一律打入冷宮。

Page 6: Ch06  介面與多重繼承

6

範例範例 1:1:1. class Ch05_012. { public static void main(String [] args)3. { Super05_01 a = new Super05_01();4. Sub05_01 b = new Sub05_01(); 5. System.out.println("a的 data: " + a.showData());6. System.out.println("b的 data: " + b.showData());7. }8. }9. class Super05_0110. {String data = "Super05_01 原始資料 ";11. String showData()12. { return data; }13. }14. class Sub05_01 extends Super05_0115. { String data = "Sub05_01 的原始資料 ";16. String showData()17. { return data; }18. }

Page 7: Ch06  介面與多重繼承

7

範例範例 2:2: 方法覆蓋時,沒有領域不同的區別,所有被方法覆蓋時,沒有領域不同的區別,所有被覆蓋的方法一律打入冷宮覆蓋的方法一律打入冷宮

1. class Ch05_022. { public static void main(String [] args)3. { Super05_02 a = new Super05_02();4. Sub05_02 b = new Sub05_02();5. a.showData();6. b.showData();7. }8. }9. class Super05_0210. { String data = "Super05_02 原始資料 ";

11. void showData()12. { System.out.println(getData()); }13. String getData()14. { return data; }15. }16. class Sub05_02 extends Super05_0217. { String data = "Sub05_02 的原始資料 ";

18. String getData()19. { return data; }20. }

Page 8: Ch06  介面與多重繼承

8

範例範例 3:3: 使用使用 supersuper 呼叫父類別方法呼叫父類別方法1. class Ch05_032. {3. public static void main(String [] args)4. {5. Super05_03 a = new Super05_03();6. Sub05_03 b = new Sub05_03();7. 8. System.out.println("a的 data: " + a.showData());9. System.out.println("b的 data: " + b.showData());10. }11. }

12. class Super05_0313. {14. String data = "Super05_03 原始資料 ";15. String showData()16. { return data; }17. }

18. class Sub05_03 extends Super05_0319. { String data = "Sub05_03 的原始資料 ";20. String showData()21. { return super.showData(); }22. }

Page 9: Ch06  介面與多重繼承

9

抽象類別抽象類別 (1/3)(1/3)

• 類別定義中,只要有一個方法(或以上)類別定義中,只要有一個方法(或以上)定義為定義為抽象方法抽象方法(( abstract methodabstract method ),則),則該類別為該類別為抽象類別抽象類別(( abstract classabstract class )。)。

• 抽象方法並沒有定義方法的主體(沒有實抽象方法並沒有定義方法的主體(沒有實作)作)

• 無法利用抽象類別建立物件。無法利用抽象類別建立物件。• 抽象類別的用處是當作父類別,讓子類別抽象類別的用處是當作父類別,讓子類別繼承。繼承。

• 子類別必須將父類別中的抽象方法實作出子類別必須將父類別中的抽象方法實作出來,才能建立物件。來,才能建立物件。

Page 10: Ch06  介面與多重繼承

10

抽象類別抽象類別 (2/3)(2/3)• 抽象類別的定義語法:抽象類別的定義語法:

修飾字 abstract class 類別名稱{

// 屬性宣告修飾字 abstract 型別 方法名稱 ( 參數列 );// 其它方法定義

}

• 某個類別的主體內,宣告了抽象方法,則該類別某個類別的主體內,宣告了抽象方法,則該類別必須宣告為抽象類別。必須宣告為抽象類別。

• 抽象類別雖然不能用以建立物件,但是可以當作抽象類別雖然不能用以建立物件,但是可以當作物件的物件的型別型別,用來宣告參照變數。,用來宣告參照變數。

• 抽象類別的子類別若不完全實作抽象方法,則依抽象類別的子類別若不完全實作抽象方法,則依然是抽象類別。然是抽象類別。

Page 11: Ch06  介面與多重繼承

11

抽象類別抽象類別 (3/3)(3/3)

• 使用抽象類別的用意,主要是「使用抽象類別的用意,主要是「制定固定制定固定的訊息接收管道,但不把焦點放在訊息的的訊息接收管道,但不把焦點放在訊息的處理上處理上」。」。

• 抽象類別和一般類別一樣,都抽象類別和一般類別一樣,都可以定義建可以定義建構子構子,只是不能直接以抽象類別的建構子,只是不能直接以抽象類別的建構子建立物件。建立物件。

• 抽象方法的目的就是為了讓子類別實作,抽象方法的目的就是為了讓子類別實作,所以所以 abstractabstract 不能同時和不能同時和 finalfinal 、、 staticstatic 或 或 privateprivate 一起使用。一起使用。

Page 12: Ch06  介面與多重繼承

12

多型多型 (polymorphism)(polymorphism)

• 不論參照的型別為何,呼叫方法時,呼叫不論參照的型別為何,呼叫方法時,呼叫最新的覆蓋方法。最新的覆蓋方法。

• 多型指的是「多型指的是「使用相同的訊息呼叫,可以使用相同的訊息呼叫,可以進行不同的功能操作進行不同的功能操作」。」。

• 動態結合動態結合(( dynamic bindingdynamic binding ):當某個物):當某個物件方法,接收傳入的件方法,接收傳入的 AA 類別之物件時,該類別之物件時,該方法無法得知傳入的是方法無法得知傳入的是 AA 類別的物件,或類別的物件,或AA 之延伸類別的物件,直到執行時才會知道,之延伸類別的物件,直到執行時才會知道,也才能知道要呼叫的是哪個方法。也才能知道要呼叫的是哪個方法。

Page 13: Ch06  介面與多重繼承

13

多型多型 (polymorphism) vs. (polymorphism) vs. 多載多載 (overload)(overload)(1/3)(1/3)

• 多載 :class 液體 _05{ String drink; 液體 _05(String drink_name) { drink = drink_name; }}class 固體 _05{ String food; 固體 _05(String food_name) { food = food_name; }}class 動物 _05{ void 吃 ( 液體 _05 a) { System.out.println(a.drink + " 是用

喝的或吸的 !"); } void 吃 ( 固體 _05 a) { System.out.println(a.food + " 是要

用咬的或磨的 !"); }}

class Ch05_05{ public static void main(String [] args) { 液體 _05 x1 = new 液體 _05(" 珍珠奶茶 "); 固體 _05 x2 = new 固體 _05(" 漢堡 "); 液體 _05 x3 = new 液體 _05("水 "); 固體 _05 x4 = new 固體 _05("草 "); 動物 _05 牛 = new 動物 _05(); 動物 _05 人 = new 動物 _05(); System.out.println("== 牛 =="); 牛 .吃 (x3); 牛 .吃 (x4); System.out.println("== 人 =="); 人 .吃 (x1); 人 .吃 (x2); }}

Page 14: Ch06  介面與多重繼承

14

多型多型 (polymorphism) vs. (polymorphism) vs. 多載多載 (overload)(overload)(2/3)(2/3)

• 多型class 動物 _06{ String kind; void 吃 ( 液體 _06 a) { System.out.println(a.drink + " 是用喝的或吸的 !"); } void 吃 ( 固體 _06 a) { System.out.println(a.food + " 是要用咬的或磨的 !"); }}class 人 _06 extends 動物 _06{ 人 _06() { kind = "人 "; } void 吃 ( 液體 _06 a) { System.out.println(a.drink + " 是用喝的 !"); } void 吃 ( 固體 _06 a) { System.out.println(a.food + " 是用咬的 !"); }}class 牛 _06 extends 動物 _06{ 牛 _06() { kind = "牛 "; } void 吃 ( 液體 _06 a) { System.out.println(a.drink + " 是用吸的 !"); } void 吃 ( 固體 _06 a) { System.out.println(a.food + " 是用磨的 !"); }}

Page 15: Ch06  介面與多重繼承

15

多型多型 (polymorphism) vs. (polymorphism) vs. 多載多載 (overload)(overload)(3/3)(3/3)

class Ch05_06{ public static void main(String [] args) { 液體 _06 x1 = new 液體 _06(" 珍珠奶茶 ");

固體 _06 x2 = new 固體 _06(" 漢堡 ");

液體 _06 x3 = new 液體 _06("水 "); 固體 _06 x4 = new 固體 _06("草 "); 牛 _06 y1 = new 牛 _06(); 人 _06 y2 = new 人 _06(); System.out.println("== " + y1.kind + "

=="); y1.吃 (x3); y1.吃 (x4); System.out.println("== " + y2.kind + "

=="); y2.吃 (x1); y2.吃 (x2); }}

class 液體 _06{ String drink; 液體 _06(String drink_name) { drink = drink_name; }}class 固體 _06{ String food; 固體 _06(String food_name) { food = food_name; }}

Page 16: Ch06  介面與多重繼承

16

物件的型別轉換• 子類別物件也屬於父類別物件子類別物件也屬於父類別物件

小紅是一條魚。小紅是一隻脊椎動物。小紅是一隻動物。

脊椎動物 無脊椎動物

界 Kingdom

門 Phylum

綱 Class

動物

哺乳類 鳥類 爬蟲類 兩棲類 魚類

植物一般化

特殊化

Page 17: Ch06  介面與多重繼承

17

範例範例 4:4:class Ch05_07{ public static void main(String [] args) { 液體 _07 x1 = new 液體 _07(" 珍珠奶茶 "); 固體 _07 x2 = new 固體 _07(" 漢堡 "); 液體 _07 x3 = new 液體 _07("水 "); 固體 _07 x4 = new 固體 _07("草 "); 動物 _07 y1 = new 牛 _07(); 動物 _07 y2 = new 人 _07(); System.out.println("== " + y1.kind + " =="); y1.吃 (x3); y1.吃 (x4); System.out.println("== " + y2.kind + " =="); y2.吃 (x1); y2.吃 (x2); }}

Page 18: Ch06  介面與多重繼承

18

物件的型別轉換 - 異質集合• 相同類別的物件集合稱為相同類別的物件集合稱為同質集合同質集合

((homogenous collectionshomogenous collections)) 。。• 不同類別的物件集合稱為不同類別的物件集合稱為異質集合異質集合

((heterogeneous collectionsheterogeneous collections)) 。。• 基本型別的陣列為同質集合。基本型別的陣列為同質集合。• 當父類別型別的當父類別型別的參照陣列參照陣列之元素分別指向之元素分別指向不同的子類別物件時,此參照陣列稱為不同的子類別物件時,此參照陣列稱為異異質集合質集合。。

• 異質集合異質集合建立在建立在父類別型別參照變數可以父類別型別參照變數可以指向子類別物件指向子類別物件的原理上。的原理上。

Page 19: Ch06  介面與多重繼承

19

物件的型別轉換 - 異質集合的物件陣列• 異質集合的物件陣列異質集合的物件陣列

a a[0]a[1]a[2]

Animal[] 型別參照 Animal 型別參照

Fish 型別物件

Vertebrate 型別物件

Animal 型別物件

Page 20: Ch06  介面與多重繼承

20

範例範例 55class Ch05_08{ public static void main(String [] args) { 液體 _08 x1 = new 液體 _08(" 珍珠奶茶 "); 固體 _08 x2 = new 固體 _08(" 漢堡 "); 液體 _08 x3 = new 液體 _08("水 "); 固體 _08 x4 = new 固體 _08("草 "); 動物 _08 y[] = {new 牛 _08(), new 人 _08()}; int i; for(i= 0; i<2; i++) { System.out.println("== " + y[i].kind + " =="); y[i].吃 (x1); y[i].吃 (x2); y[i].吃 (x3); y[i].吃 (x4); } }}

Page 21: Ch06  介面與多重繼承

21

物件的強制型別轉換 (1/3)

• 物件型別轉換,其實是物件型別轉換,其實是針對指向物件的參針對指向物件的參照變數照變數,,而不是針對物件實體而不是針對物件實體。物件實體。物件實體只要被建立,其佔用的記憶體位置及大小只要被建立,其佔用的記憶體位置及大小都不會被變更。都不會被變更。

• 物件的強制型別轉換之語法物件的強制型別轉換之語法( 目的類別 ) 物件參照變數

• 物件參照變數所指向的物件實體,必須是目的類別的物件實體,或是其子類別的物件實體。

Page 22: Ch06  介面與多重繼承

22

物件的強制型別轉換 (2/3)

• 子類別物件轉換成父類別物件子類別物件轉換成父類別物件

子類別定義之成員

父類別定義之成員

子類別物件

父類別定義之成員

父類別物件

物件型別轉換

不能使用

Page 23: Ch06  介面與多重繼承

23

物件的強制型別轉換 (3/3)

• 父類別物件不具備父類別物件不具備子類別定義之成員子類別定義之成員,無法轉換,無法轉換成子類別物件。成子類別物件。

無法轉換

父類別定義之成員

父類別物件子類別定義之成員

父類別定義之成員

子類別物件

從何而來?

Page 24: Ch06  介面與多重繼承

24

instanceof運算子• instanceofinstanceof 運算式會得到一個布林值,若物運算式會得到一個布林值,若物件名稱所指向的物件實體屬於欲判斷的類件名稱所指向的物件實體屬於欲判斷的類別則回傳別則回傳 truetrue ;反之,回傳;反之,回傳 falsefalse 。。– 物件名稱  instanceof  類別名稱

• 物件名稱物件名稱所屬的所屬的參照型別參照型別必須和必須和類別名稱類別名稱有繼承關係,否則會發生錯誤。有繼承關係,否則會發生錯誤。

• instanceofinstanceof 的優先權和關係運算子的 的優先權和關係運算子的 << 、、>> 、、 <=<= 、、 >= >= 相同,它們的運算結果都是相同,它們的運算結果都是布林值。布林值。

Page 25: Ch06  介面與多重繼承

25

動腦動手時間動腦動手時間 (1)(1)

• 請以範例 4,5,6,7,8 為參考• 建立一個程式 :

– 食物類別 : 食物名稱• 液體類別• 固體類別

– 動物類別 :吃 ()• 人類別 :吃 ( 固體 ), 吃 ( 液體 )• 牛類別 :吃 ( 固體 ), 吃 ( 液體 )

• 人和牛要吃所有的食物

Page 26: Ch06  介面與多重繼承

26

動腦動手時間動腦動手時間 (2)(2)• 考慮一商店買賣系統• 商店有貨品 :

– 湯瑪士 :進貨 50,單價 290– 培西 :進貨 40,單價 290– 哈諾 :進貨 20,單價 290

• 執行下列動作 :– 賣 (湯瑪士 , 10)– 賣 (培西 , 5)– 特價 (哈諾 , 190)– 賣 (湯瑪士 ,60)– 賣 (哈諾 , 10)

• 輸出 :– 每次賣東西後 , 都要針對該筆交易產生帳單– 每次賣東西後 , 要顯示現在存貨– 每次有更新 , 也要顯示狀況– 最後 ,顯示庫存及單價

Page 27: Ch06  介面與多重繼承

27

abstract class 食物 _ex1{ String food_name; abstract void 吃的方式 ();}class 液體 _ex1 extends 食物 _ex1{ 液體 _ex1(String drink_name) { food_name = drink_name; } void 吃的方式 () { System.out.println(" 喝的 "); }}class 固體 _ex1 extends 食物 _ex1{ 固體 _ex1(String food) { food_name = food; } void 吃的方式 () { System.out.println("嚼的 "); }}

Page 28: Ch06  介面與多重繼承

28

• abstract class 動物 _ex1• {• String kind;• abstract void 吃 ( 食物 _ex1 a);• }• class 人 _ex1 extends 動物 _ex1• {• 人 _ex1()• {• kind = "人 ";• } • void 吃 ( 食物 _ex1 a)• {• if (a instanceof 液體 _ex1)• {• System.out.print(a.food_name + " 是用杯子 ");• a. 吃的方式 ();• }• else• {• System.out.print(a.food_name + " 是用牙齒 "); • a. 吃的方式 ();• }• }• }• class 牛 _ex1 extends 動物 _ex1• {• 牛 _ex1()• {• kind = "牛 ";• }• void 吃 ( 食物 _ex1 a)• {• if (a instanceof 液體 _ex1)• {• System.out.print(a.food_name + " 是用舌頭 ");• a. 吃的方式 ();• }• else• {• System.out.print(a.food_name + " 是用臼齒 "); • a. 吃的方式 ();• }• }• }

Page 29: Ch06  介面與多重繼承

29

• class Ex05_01• {• public static void main(String [] args)• {• 食物 _ex1 x[] = {new 液體 _ex1(" 珍珠奶茶 "), new 固體

_ex1(" 漢堡 "), new 液體 _ex1("水 "), new 固體 _ex1("草 ")};• 動物 _ex1 y[] = {new 牛 _ex1(), new 人 _ex1()};• int i, j;• for(i= 0; i<2; i++)• {• System.out.println("== " + y[i].kind + " ==");• for(j = 0; j < 4; j++)• {• y[i].吃 (x[j]);• }• }• }• }

Page 30: Ch06  介面與多重繼承

薪資系統薪資系統 (1/8)(1/8)1. abstract class 員工2. {

3. String 姓名 ;

4. String 工作部門 ;

5. int 薪水 ;

6. 員工 (String name, String dept)

7. {

8. 姓名 = name;

9. 工作部門 = dept;

10. }

11. void print薪資單 ()

12. {

13. System.out.println("薪資單 ");

14. System.out.println("姓名 : " + 姓名 + " 工作部門 : " + 工作部門 );

15. }

16.

17. abstract void 薪水 ();

18. }

30

Page 31: Ch06  介面與多重繼承

薪資系統薪資系統 (2/8)(2/8)1. abstract class 正職 extends 員工2. {

3. int 月薪 ;

4. 正職 (String name, String dept, int salary)

5. {

6. super(name, dept);

7. 月薪 = salary;

8. }

9. void print薪資單 ()

10. {

11. super.print薪資單 ();

12. System.out.println("月薪 : " + 月薪 );

13. }

14. }

31

Page 32: Ch06  介面與多重繼承

薪資系統薪資系統 (3/8)(3/8)1. abstract class 兼職 extends 員工2. {

3. int 工資 ;

4. 兼職 (String name, String dept)

5. {

6. super(name, dept);

7. }

8. void print薪資單 ()

9. {

10. super.print薪資單 ();

11. System.out.println("工資 : " + 工資 );

12. }

13. }

32

Page 33: Ch06  介面與多重繼承

薪資系統薪資系統 (4/8)(4/8)1. class 主管 extends 正職2. {

3. 主管 (String name, String dept, int salary)

4. {

5. super(name, dept, salary);

6. }

7. void print薪資單 ()

8. {

9. super.print薪資單 ();

10. System.out.println("總計 : " + 薪水 );

11. }

12. void 薪水 ()

13. {

14. 薪水 = 月薪 ;

15. }

16. }33

Page 34: Ch06  介面與多重繼承

薪資系統薪資系統 (5/8)(5/8)1. class 一般員工 extends 正職2. {

3. int 加班費 ;

4. 一般員工 (String name, String dept, int salary, int h)

5. {

6. super(name, dept, salary);

7. 加班費 = h * 100;

8. }

9. void print薪資單 ()

10. {

11. super.print薪資單 ();

12. System.out.println("加班費 : " + 加班費 );

13. System.out.println("總計 : " + 薪水 );

14. }

15.

16. void 薪水 ()

17. {

18. 薪水 = 月薪 + 加班費 ;

19. }

20. }

34

Page 35: Ch06  介面與多重繼承

薪資系統薪資系統 (6/8)(6/8)1. class 業務員 extends 正職2. {

3. int 業績獎金 ;

4. 業務員 (String name, String dept, int salary, int 業績 )

5. {

6. super(name, dept, salary);

7. 業績獎金 = 業績 * 5 / 100;

8. }

9. void print薪資單 ()

10. {

11. super.print薪資單 ();

12. System.out.println("業績獎金 : " + 業績獎金 );

13. System.out.println("總計 : " + 薪水 );

14. }

15. void 薪水 ()

16. {

17. 薪水 = 月薪 + 業績獎金 ;

18. }

19. }

35

Page 36: Ch06  介面與多重繼承

薪資系統薪資系統 (7/8)(7/8)1. class 計件工作人員 extends 兼職2. {

3. 計件工作人員 (String name, String dept, int 件數 )

4. {

5. super(name, dept);

6. 工資 = 件數 * 10;

7. }

8. void print薪資單 ()

9. {

10. super.print薪資單 ();

11. System.out.println("總計 : " + 薪水 );

12. }

13. void 薪水 ()

14. {

15. 薪水 = 工資 ;

16. }

17. }

36

Page 37: Ch06  介面與多重繼承

薪資系統薪資系統 (8/8)(8/8)1. class 計時工作人員 extends 兼職2. {

3. 計時工作人員 (String name, String dept, int h)

4. {

5. super(name, dept);

6. 工資 = h * 100;

7. }

8. void print薪資單 ()

9. {

10. super.print薪資單 ();

11. System.out.println("總計 : " + 薪水 );

12. }

13. void 薪水 ()

14. {

15. 薪水 = 工資 ;

16. }

17. }

37

Page 38: Ch06  介面與多重繼承

JAVAJAVA 程式設計程式設計

以 [ 大富翁 ] 為例

Page 39: Ch06  介面與多重繼承

V8:V8: 抽象類別抽象類別-- 以玩家可以有不同個性為例以玩家可以有不同個性為例

1.學習抽象類別2.學習抽象方法3.學習異質集合

Page 40: Ch06  介面與多重繼承

// 土地類別沒有更動class 土地{ String 地名 ;

int 過路費 = 20;

int 地價 ;

玩家 地主 ;

土地 (String 地名 )

{ this.地名 = 地名 ;

}

土地 (String name, int price)

{ 地名 = name;

地價 = price;

}

void 登記土地所有權人 (玩家 買地人 )

{ if( 買地人 .錢 >= 地價 )

{ // 有錢可以買地 買地人 .錢 -= 地價 ;

地主 = 買地人 ;

System.out.println( 買地人 . 名字 + " 買了 " + 地名 );

}

else

System.out.println( 買地人 . 名字 + " 沒有買地 ");

return;

}

}

Page 41: Ch06  介面與多重繼承

// 土地 2 多加一個 [ 登記土地所有權人 ] 的方法,只是為了連結到父類別的[登記土地所有權人]方法

class 土地 2 extends 土地{ int [] 過路費 = new int[6];

int 房子數 = 0;

土地 2(String 地名 )

{ super(地名 );

for(int i = 0; i < 過路費 .length; i++)

過路費 [i] = 20 + i*10;

}

土地 2(String name, int price)

{ super(name);

地價 = price;

for(int i = 0; i < 過路費 .length; i++)

過路費 [i] = 20 + i*10;

}

void 登記土地所有權人 (玩家 買地人 )

{ super.登記土地所有權人 ( 買地人 );

}

}

Page 42: Ch06  介面與多重繼承

// 將原來的類別改成抽象類別,並加上抽象方法[購地策略]abstract class 玩家{ String 名字 ;

int 錢 = 2000;

int 位置 = 0;

玩家 (String name)

{ 名字 = name;

}

void 前進 ()

{ 位置 += ((int)(Math.random()*11) + 2);

if ( 位置 >= 40)

{ 位置 -= 40;

錢 += 1000;

}

return;

}

void 付過路費 (土地 2 路過此地 )

{ 錢 -= 路過此地 . 過路費 [路過此地 .房子數 ];

路過此地 .地主 .錢 += 路過此地 . 過路費 [路過此地 .房子數 ];

System.out.println( 名字 + " 要付給 " + 路過此地 .地名 + " 的地主 " +路過此地 .地主 . 名字 + " " + 路過此地 . 過路費 [路過此地 .房子數 ] + " 元 ");

}

abstract void 購地策略 (土地 2 l);

}

Page 43: Ch06  介面與多重繼承

// 建立兩個子類別,並實作父類別的抽象方法[購地策略]class 我就是要買 extends 玩家{ 我就是要買 (String name)

{ super(name);

}

void 購地策略 (土地 2 l)

{ l.登記土地所有權人 (this);

}

}

class 打死不買 extends 玩家{ 打死不買 (String name)

{ super(name);

}

void 購地策略 (土地 2 l)

{ System.out.println( 名字 + " 是打死不買 , 所以不買就是不買 ");

}

}

Page 44: Ch06  介面與多重繼承

// 在主程式的部份,利用異質陣列,只需在配置空間時,宣告為[打死不買]和[我就是要買]的不同類別物件

class 大富翁{ public static void main(String [] args)

{String [] 土地名 = {" 中華民國 ", "日本 ", "韓國 ", "菲律賓 ", "馬來西亞 ",

"越南 ", "泰國 ", "印度 ", "伊拉克 ", "伊朗 ",

"沙烏地阿拉伯 ", "土耳其 ", " 以色列 ", "蘇俄 ", "波蘭 ",

"德國 ", "奧地利 ", "瑞士 ", " 法國 ", "比利時 ",

"荷蘭 ", "英國 ", "芬蘭 ", "瑞典 ", "丹麥 ",

"希臘 ", " 義大利 ", "西班牙 ", "葡萄牙 ", "埃及 ",

"摩洛哥 ", "南非 ", "加拿大 ", "美國 ", "墨西哥 ",

"宏都拉斯 ", "尼加拉瓜 ", "古巴 ", "巴拿馬 ", "巴西 "} ;

String [] PN = {"喜羊羊 ", "美羊羊 ", " 小灰灰 ", "灰太狼 "};

土地 2 L [] = new 土地 2[40];

for (int i = 0; i < L.length; i++)

{

if(i/2 * 2 == i)

L[i] = new 土地 2(土地名 [i], i*20);

else

L[i] = new 土地 2(土地名 [i]);

// L[i].地名 = 土地名 [i];

System.out.println(L[i].地名 + " 地價是 " + L[i].地價 );

}

Page 45: Ch06  介面與多重繼承

// 異質陣列玩家 P [] = new 玩家 [4];

for (int i = 0; i < P.length-2; i++)

{ P[i] = new 打死不買 (PN[i]);

}

for(int i = 2; i < P.length; i++)

{ P[i] = new 我就是要買 (PN[i]);

}

//P[0]. 名字 = "喜羊羊 ";

//P[1]. 名字 = "美羊羊 ";

//P[2]. 名字 = " 小灰灰 ";

//P[3]. 名字 = "灰太狼 ";

for(int j = 1; j <= 5; j++)

{

System.out.println("第 " + j + " 輪 ");

/* System.out.println(" 目前土地狀態 ");

for (int k = 0; k < L.length; k++)

{

if( L[k].地主 != null)

System.out.println(L[k].地名 + " 地主是 " + L[k].地主 . 名字 );

else

System.out.println(L[k].地名 );

}

*/

Page 46: Ch06  介面與多重繼承

for(int i = 0; i < P.length; i++)

{

P[i].前進 ();

System.out.println(P[i]. 名字 + " 在 " + L[(P[i]. 位置 )].地名 + ", 現在有錢 " +P[i].錢 );

if(L[P[i]. 位置 ].地主 == null)

{ // 買地 P[i].購地策略 (L[P[i]. 位置 ]);

// System.out.println(L[P[i]. 位置 ].地名 + " 目前尚未售出 ");

// L[P[i]. 位置 ].登記土地所有權人 (P[i]);

}

else

{ //付過路費 if (L[P[i]. 位置 ].地主 != P[i])

{

P[i].付過路費 (L[P[i]. 位置 ]);

}

System.out.println(P[i]. 名字 + " 在 " + L[(P[i]. 位置 )].地名 + ", 現在有錢 " +P[i].錢 );

}

}

}

}

}