ch01 物件與類別複習
DESCRIPTION
Ch01 物件與類別複習. 物件導向系統實務. 本章大綱. 以實例介紹物件導向的概念 以文字問答敘述複習物件類別的概念. 第一部份. 以實例介紹物件導向的概念. 類別與物件 (1/3). 實際世界:有一家吸塵機器人的製造工廠,工廠生產會自動行走的吸塵器,工廠生產了 1000 台機器。我家買了一台,你家也買了一台 物件:每一台吸塵機器人都有自己的實體,實體內包含有自己的名字、顏色 … 等特性值,例如: 我家的吸塵機器人、你家的吸塵機器人、還有其他的 998 台吸塵機器人 類別:包含屬性(特性)、建構子、方法(動作)等的設定,例如: 生產線上的模子. - PowerPoint PPT PresentationTRANSCRIPT
Ch01 Ch01 物件與類別複習物件與類別複習物件導向系統實務
本章大綱• 以實例介紹物件導向的概念• 以文字問答敘述複習物件類別的概念
第一部份
以實例介紹物件導向的概念
類別與物件 (1/3)
實際世界:有一家吸塵機器人的製造工廠,工廠生產會自動行走的吸塵器,工廠生產了 1000 台機器。我家買了一台,你家也買了一台• 物件:每一台吸塵機器人都有自己的實體,實體內包含有自己的名字、顏色…等特性值,例如:我家的吸塵機器人、你家的吸塵機器人、還有其他的 998 台吸塵機器人• 類別:包含屬性(特性)、建構子、方法(動作)等的設定,例如:生產線上的模子
類別與物件 (2/3)
• 主程式:1. class ourWorld2. { public static void main(String [] args)3. { 吸塵機器人 robot1 = new 吸塵機器
人 (“toto”, “ 銀灰色” );4. 吸塵機器人 robot2 = new 吸塵機器
人 (“ 月餅” , “ 紅色” );5. }
6. }
• 類別:吸塵機器人1. class 吸塵機器人2. { // 屬性3. String name;4. String color;5. // 建構子6. 吸塵機器人 (String name, String
color)7. { this.name = name;8. this.color = color;9. }10. // 方法11. void 吸塵 (){…}12. }
類別與物件 (3/3)
name:Stringcolor:String
吸塵機器人
吸塵 ():void
name:String = totocolor:String= 銀灰robot1: 吸塵機器人
吸塵 ():void
name:String= 月餅color:String= 紅robot2: 吸塵機器人
吸塵 ():void
instanceOf instanceOf
類別-如何建立一個類別 (1/4)
• 類別的建立有兩個方法:1. 自己一行一行程式的去完成2. 善用已經存在的類別去組合完成
類別-如何建立一個類別 (2/4)實際世界:吸塵機器人的模子是這樣做的,吸塵機器人需要有三個技術結合:1. 吸塵器2. 感應器(偵測是否撞到墻 ? )3. 自動行走(類似玩具小汽車,會利用電力來前進)工廠的設計部門當然不會自己設計這三個技術,他們會花錢購買這三個技術,再將這三個技術結合,再補加上一些設計,一個吸塵機器人的模子就完成了!以物件導向的概念來看:父類別:包含吸塵器、感應器、自動行走等類別子類別:吸塵機器人繼承:子類別繼承父類別,即子類別是新產物,而父類別是舊(已)有的技術但是, JAVA 是單一繼承,所以,在父類別中,吸塵器應該是吸塵機器人真正的父親;而感應器和自動行走,我們可以視為其輔助功能,我們以介面來實現介面:類似類別,但是其方法沒有實作
類別-如何建立一個類別 (3/4)
• 繼承關係:
name:Stringcolor:String
吸塵機器人
吸塵 ():void感應 ():void走 ():void
name:String = totocolor:String=銀灰robot1:吸塵機器人
吸塵 ():void
name:String=月餅color:String=紅robot2:吸塵機器人
吸塵 ():void
instanceOf instanceOf
吸塵器
吸塵 ():void
<interface>感應器
感應 ():void
<interface> 自動行走
走 ():void
類別-如何建立一個類別 (4/4)• 類別:吸塵器1. class 吸塵器2. { void 吸塵 ()3. {…}4. }• 介面:感應器1. interface 感應器2. { void 感應 ();3. }• 介面:自動行走1. interface 自動行走2. {void 走 ();3. }
• 類別:吸塵機器人1. class 吸塵機器人 extends 吸塵器
implements 感應器 , 自動行走2. { // 屬性3. String name;4. String color;5. // 建構子6. 吸塵機器人 (String name, String color)7. { this.name = name;8. this.color = color;9. }10. // 方法11. void 吸塵 (){…}12. void 感應 () { 撞到東西原地打轉 ;}13. void 走 () { 直直的走 ; }14. }
多載 (1/3)
實際世界:吸塵機器人已雛型完成,因為是智慧型的機器人,它會自己判斷現在地上是灰塵,還是可樂,還是固體加上液體。這在物件導向程式設計中就是多載:在一個類別中,有多個同名的方法,方法的回傳及參數個數或型式不同,例如:void 吸塵 ( 液體 )void 吸塵 ( 固體 )void 吸塵 ( 液體,固體 )
多載 (2/3)• 類別:吸塵機器人1. class 吸塵機器人 extends 吸塵器 implements 感應器 , 自動行走2. { // 屬性3. String name;4. String color;5. // 建構子6. 吸塵機器人 (String name, String color)7. { this.name = name;8. this.color = color;9. }10. // 方法11. void 吸塵 ( 液體 ){…}12. void 吸塵 ( 固體 ){xxx}13. void 吸塵 ( 液體 , 固體 ) {ccc}14. void 感應 () { 撞到東西原地打轉 ;}15. void 走 () { 直直的走 ; }16. }
多載 (3/3)
name:Stringcolor:String
吸塵機器人
吸塵 ( 液體 ):void吸塵 ( 固體 ):void吸塵 ( 液體 , 固體 ):void感應 ():void走 ():void
name:String = totocolor:String= 銀灰robot1: 吸塵機器人
吸塵 ( 液體 ):void吸塵 ( 固體 ):void吸塵 ( 液體 , 固體 ):void感應 ():void走 ():void
name:String= 月餅color:String= 紅robot2: 吸塵機器人
吸塵 ( 液體 ):void吸塵 ( 固體 ):void吸塵 ( 液體 , 固體 ):void感應 ():void走 ():void
instanceOf instanceOf
吸塵器
吸塵 ():void
<interface> 感應器
感應 ():void
<interface> 自動行走
走 ():void
多型 (1/3)實際世界:工廠發現所設計的機器人打掃結果不理想,設計部門要做部份的修改,再生產吸塵機器人二世代。設計修改的部份是「走」,設計師發現原來的行動方向是類似「直線前進」,現在要做三種機器人:機器人-A型:如乒乓球般撞到墻,會有一個回彈角度機器人-B型:每次撞到墻,會產生一個亂數斜率,再以此斜率前進機器人-C型:每次以旋轉方式前進
多型 (2/3)
name:Stringcolor:String
吸塵機器人
吸塵 ( 液體 ):void吸塵 ( 固體 ):void吸塵 ( 液體 , 固體 ):void感應 ():void走 ():void
name:String = totocolor:String= 銀灰robot1: 吸塵機器人
吸塵 ( 液體 ):void吸塵 ( 固體 ):void吸塵 ( 液體 , 固體 ):void感應 ():void走 ():void
name:String= 月餅color:String= 紅robot2: 吸塵機器人
吸塵 ( 液體 ):void吸塵 ( 固體 ):void吸塵 ( 液體 , 固體 ):void感應 ():void走 ():void
instanceOf instanceOf
吸塵器
吸塵 ():void
<interface> 感應器
感應 ():void
<interface> 自動行走
走 ():void
機器人二世代 -A
走 ():void{ 直直的走 ;}
機器人二世代 -B
走 ():void{ 亂數斜率的走 ;}
機器人二世代 -C
走 ():void{ 螺旋型的走 ;}
多型 (3/3)• 類別 : 二世代 -A1. class 機器人二世代 -A extends 吸塵機器人2. { void 走 ()3. { 直直的走 ; }4. }• 類別 : 二世代 -B1. class 機器人二世代 -B extends 吸塵機器人2. { void 走 ()3. { 亂數斜率的走 ; }4. }• 類別 : 二世代 -C1. class 機器人二世代 -C extends 吸塵機器人2. { void 走 ()3. { 螺旋的走 ; }4. }
如果在 main 方法中告一個物件 x1 如下 :機器人二世代 -B x1 = new 機器人二世代 -B();問題 :x1 怎麼走 ?
如果在 main 方法中宣告一個物件 x2 如下 :吸塵機器人 x2 = new 機器人二世代 -C();問題 : x2 怎麼走 ?
第二部份
以文字問答敘述複習物件類別的概念
112/04/24 18112/04/24 18
類別與物件• 程式之主體類別,其名稱必須與其儲存檔案之主檔名相同• 主程式起始位置之字串 public static void
main(String [] args)• 物件之屬性或成員以句點“ .”描述之
112/04/24 19112/04/24 19
Q1: 類別與物件1. class myNumber { 2. int number; 3. } 4. 5. class Ex2_1_1 { 6. public static void main(String[] args) { 7. myNumber a; 8. a= new myNumber(); 9. a.number= 5;10. System.out.println("a.number= "+a.number);11. }12. }
+number : intmyNumber
number : inta : myNumber
112/04/24 20112/04/24 20
Q2: 原始型態與參考型態• 原始型態為系統預設資料型態,如
int 、 char 、 float 、 long 、 boolean 等,可直接給予資料• 參考資料為以設計之類別為資料型態,附以變數之型態,所以參考型態變數應先產生新物件,再給予資料
112/04/24 21112/04/24 21
Q2: 原始型態與參考型態1. class myNumber { 2. int i; 3. } 4. 5. class Ex2_2_1 { 6. public static void main(String[] args) { 7. int j;8. myNumber a;
9. j=3; 10. 11. a = new myNumber(); 12. a.i=5;13. System.out.println("j="+j);14. System.out.println("a.i="+a.i);15. }16. }
+i : intmyNumber
i : inta : myNumber
112/04/24 22112/04/24 22
Q3: 生存物件之變數 ( 屬性 )
• 當以某類別為資料型態之物件尚未建立時,其中所宣告之屬性,均無法存取。• 如果要使用這些屬性,就必須先產生其所屬之物件
112/04/24 23112/04/24 23
Q3: 生存物件之變數 ( 物件屬性 )
1. class MyClass1 {2. int i;3. }
4. class Ex2_4_1 {5. int j;
6. public static void main(String[] args) {7. i = 3; 8. j = 5;9. System.out.println("i="+i);10. System.out.println("j="+j);11. }12. }
112/04/24 24112/04/24 24
Q3: 生存物件之變數 ( 物件屬性 )1. class MyClass1 {
2. int i;3. }
4. class Ex2_4_2 {5. int j;
6. public static void main(String[] args) {7. MyClass1 a = new MyClass1();8. Ex2_4_2 b = new Ex2_4_2();
9. a.i=3;10. b.j=5;
11. System.out.println("i="+a.i);12. System.out.println("j="+b.j);13. }14. }
112/04/24 25112/04/24 25
Q4: 類別之變數 ( 類別屬性 )
• 於類別中宣告之變數,若加上 static ,該變數即謂類別變數,否則是生存物件變數• 類別變數可直接使用,不必先產生物件• 類別變數是同一類別中所有物件所共有,而不是屬於某個物件
112/04/24 26112/04/24 26
Q4: 類別之變數1. class MyClass1 {2. static int i;3. }
4. class Ex2_5_1 {5. static int j;
6. public static void main(String[] args) {7. MyClass1.i = 3; 8. j = 5;9. System.out.println("i="+MyClass1.i);10. System.out.println("j="+j);11. }12. }
#i : intMyClass1
#j : intEx2_5_1
112/04/24 27112/04/24 27
Q4: 類別之變數1. class MyClass1 {2. static int i;3. }
4. class Ex2_5_2 {5. static int j;6. public static void main(String[] args) {7. MyClass1 a = new MyClass1();8. Ex2_5_2 b = new Ex2_5_2();9. MyClass1 c = new MyClass1();10. a.i=3;11. b.j=5;12. System.out.println("i="+a.i);13. System.out.println("j="+b.j);14. System.out.println("c.i="+c.i);15. System.out.println("MyClass1.i="+MyClass1.i);16. System.out.println("Ex2_5_2.j="+j);17. }18. }
#i : intMyClass1
#j : intEx2_5_1
i : int = 3a : MyClass1
j : int = 5b : Ex2_5_1
112/04/24 28112/04/24 28
Q5: 方法• 類別中,所宣告之方法,類似一般高階語言的副程式• 使用方法時,須先產生新物件再執行各新物件內之方法• 使用 ( 呼叫)方法時,要注意傳入參數之一致性
– 參數型態一致– 參數數量一致
• 宣告方法時,若無回傳資料,必須前置 void ,若有回傳資料,要註明回傳資料型態,且要有return
112/04/24 29112/04/24 29
Q5: 方法1. class Study {2. private int credit=0; 3. void addcredit(int i) { credit += i; } 4. int totalcredit() { return credit; } 5. }6. class Ex2_6_1 {7. public static void main(String[] args) {8. Study joe = new Study(); 9. Study george = new Study();10. joe.addcredit(12); 11. george.addcredit(9);12. joe.addcredit(6); 13. george.addcredit(3);14. System.out.println("joe studied:"+joe.totalcredit()+"credites");15. System.out.println("george studied:"+george.totalcredit()
+"credites"); 16. }17. }
+addcredit()+totalcredit() : int
-credit : int = 0study
credit : int = 0joe : study
credit : int = 0george : study
+addcredit()+totalcredit()
-credit : intjoe:study
+addcredit()+totalcredit()
-credit : intgeorge:study
112/04/24 30112/04/24 30
Q6: 物件方法• 當方法所屬之物件尚未產生之前,該方法是無法執行的
112/04/24 31112/04/24 31
Q6: 物件方法1. class Mynumber {2. public int number; 3. public void setnumber(int i) { number = i; } 4. public int getnumber() { return number; } 5. }
6. class Ex2_7_1{7. public static void main(String[] args) {8. Mynumber.setnumber(3);9. System.out.println("number= "+Mynumber.number); 10. }11. }
+setnumber()+getnumber() : int
+number : intMynumber
112/04/24 32112/04/24 32
Q6: 物件方法1. class Mynumber {2. public int number; 3. public void setnumber(int i) { number = i; } 4. public int getnumber() { return number; } 5. }
6. class Ex2_7_2{7. public static void main(String[] args) {8. Mynumber a= new Mynumber();9. a.setnumber(3);10. System.out.println("number= "+a.getnumber()); 11. }12. }
+setnumber()+getnumber() : int
+number : intMynumber
number : inta : Mynumber
112/04/24 33112/04/24 33
Q7: 類別方法• 類別方法於宣告時須前置 static• 類別方法不同於物件方法,類別方法可直接使用• 類別方法不可以直接呼叫物件方法,因為物件方法要先有物件存在,呼叫時要加上物件 . 方法()• 物件方法可以直接呼叫類別方法
112/04/24 34112/04/24 34
Q7: 類別方法1. class Mynumber {2. public static int number; 3. public static void setnumber(int i) { number = i; } 4. public static int getnumber() { return number; } 5. }
6. class Ex2_8_1{7. public static void main(String[] args) {8. Mynumber.setnumber(3);9. System.out.println("number= "+Mynumber.number); 10. }11. }
112/04/24 35112/04/24 35
Q8: 建構子• 建構子之名稱必須與所屬類別之名稱相同• 在沒有定義建構子的類別時,編繹器會自動設給一個沒有形式參數的建構子• 建構子無回傳資料,內容無 return ,宣告中亦不得前置 void• 建構子主要功能是在所屬類別產生新物件時作初始化動作
112/04/24 36112/04/24 36
Q8: 建構子1. class Mynumber {2. int number;3.4. Mynumber() { 5. System.out.println("Here is Constructor"); 6. number = 3; 7. }8. int getnumber() { return number; }9. }
10. class Ex2_9_1 {11. public static void main(String[] args) {12. Mynumber a = new Mynumber();13. System.out.println("Here is main: "+a.getnumber());14. }15. }
+Mynumber()+getnumber() : int
+number : intMynumber
number : inta : Mynumber
+Mynumber()+getnumber() : int
-number : inta:Mynumber
112/04/24 37112/04/24 37
Q9: 方法多載• 方法多載之定義為:在同一類別內,有兩個(含)以上之方法,具有相同之名稱,但其宣告之類型或參數個數卻不相同• 其目的是因應不同的傳遞資料,讓方法更有彈性
112/04/24 38112/04/24 38
Q9: 方法多載1. class adder{2. int add(int i,int j){return i+j;}3. double add(double i,double j){return i+j;}4. }
5. class Ex2_10_1{6. public static void main(String[] args){7. int n;8. double x;
9. adder a= new adder();10. n=a.add(2,3);11. x=a.add(2.2, 3.3);12. System.out.println("int n = " + n);13. System.out.println("double x = " + x);14. }15. }
+add() : int+add() : double
adder
a : adder
112/04/24 39112/04/24 39
Q9: 方法多載1. class adder{2. int n;3. double x;4. adder(int i, int j){5. n= i+j;6. System.out.println("use_int= "+n);7. }
8. adder(double i, double j){9. x= i+j;10. System.out.println("use_double= "+x);11. }12. }13. class Ex2_10_2{14. public static void main(String[] args){15. adder use_int= new adder(2,3);16. adder use_double= new adder(2.2, 3.3);17. }18. }
+adder() : int+adder() : double
adder
use_int : adder use_double : adder
112/04/24 40112/04/24 40
Q10: public( 公用 )/private( 私用 ) 存取設定• 當變數前置 public時,即為公用變數,其他物件均可存取應用• 當變數前置 private時,即為私用變數,只有類別內宣告的方法可以取用,其他物件均不得存取應用• 當變數無前置任何存取設定時,僅允許在,同一 package 存取應用
112/04/24 41112/04/24 41
Q10: public( 公用 )/private( 私用 ) 存取設定1. class Mynumber {2. int i;3. public int j;4. }
5. class Ex2_11_1 {6. public static void main(String[] args) {7. Mynumber a = new Mynumber();8. a.i = 10;9. a.j = 20;10.11. System.out.println("a.i = "+a.i+", a.j = "+a.j);12. }13. }
#i : int+j : int
Mynumber
i : intj : int
a : Mynumber
112/04/24 42112/04/24 42
Q10: public( 公用 )/private( 私用 ) 存取設定1. class Mynumber {2. int i;3. private int j;4. }
5. class Ex2_11_2 {6. public static void main(String[] args) {7. Mynumber a = new Mynumber();8. a.i = 10;9. a.j = 20;10.11. System.out.println("a.i = "+a.i+", a.j = "+a.j);12. }13. }
#i : int-j : int
Mynumber
i : intj : int
a : Mynumber
112/04/24 43112/04/24 43
Q10: public( 公用 )/private( 私用 ) 存取設定1. class Mynumber {2. int i;3. private int j;4. }
5. class Ex2_11_2 {6. private int k = 10;7. public static void main(String[] args) {8. Mynumber a = new Mynumber();9. a.i = 10;10. Ex2_11_2 b = new Ex2_11_2();11. //a.j = 20;12.13. System.out.println("a.i = "+a.i);14. System.out.println("b.k = " +b.k);15. }16. }
#i : int-j : int
Mynumber
i : intj : int
a : Mynumber
112/04/24 44112/04/24 44
Q10: public( 公用 )/private( 私用 ) 存取設定1. class Mynumber {2. private int number;3. public void setnumber(int i) { number=i;} 4. public int getnumber() { return number; } 5. }
6. class Ex2_11_3 {7. public static void main(String[] args) {8. Mynumber a = new Mynumber();
9. a.setnumber(10);10. System.out.println("result= "+a.getnumber());11. }12. }
+setnumber()+getnumber() : int
-number : intMynumber
number : inta : Mynumber
112/04/24 45112/04/24 45
Q11: this 之應用• This之意義為所屬類別之代名詞• This 可用於建構子間之呼叫
–使用 this呼叫建構子時,僅可在一建構子中,呼叫另一建構子–使用 this呼叫建構子時, this 必須置於第一行– 不能造成建構子遞迴
112/04/24 46112/04/24 46
Q11: this 之應用1. class Mynumber {2. private int number;3. public Mynumber(int i){4. this.number= i;5. }6. public int getnumber(){return number;} 7. }
8. class Ex2_12_1 {9. public static void main(String[] args) {10. Mynumber a = new Mynumber(10);11. System.out.println("result= "+a.getnumber());12. }13. }
+setnumber()+getnumber() : int
-number : intMynumber
number : inta : Mynumber
112/04/24 47112/04/24 47
Q11: this 之應用1. class Mynumber {2. private int number;
3. public Mynumber(int i){ this.number= i; }4. public Mynumber(int j, String s){ this(j); }
5. public int getnumber(){ return number; } 6. }
7. class Ex2_12_2 {8. public static void main(String[] args) {9. Mynumber a = new Mynumber(10, "stringtest");10. System.out.println("result= "+a.getnumber());11. }12. }
+setnumber()+getnumber() : int
-number : intMynumber
number : inta : Mynumber
112/04/24 48112/04/24 48
Q12: 物件陣列1. class Mynumber {2. private int number;3. public void setnumber(int i) { number=i;} 4. public int getnumber() { return number; } 5. }6. class Ex2_13_1 {7. public static void main(String[] args) {8. int[] intArray; 9. Mynumber[] MyArray; 10. intArray = new int[2];11. intArray[0] = 5;12. intArray[1] = 10;13. System.out.println("intArray[0]= "+intArray[0]);14. System.out.println("intArray[1]= "+intArray[1]);15. MyArray = new Mynumber[2];16. MyArray[0] = new Mynumber();17. MyArray[1] = new Mynumber();18. MyArray[0].setnumber(15);19. MyArray[1].setnumber(20);20. System.out.println("MyArray[0].number= "+MyArray[0].getnumber());21. System.out.println("MyArray[1].number= "+MyArray[1].getnumber());22. }}
+setnumber()+getnumber() : int
-number : intMynumber
112/04/24 49112/04/24 49
Q13: 巢狀類別應用• 類別的定義也可以放置於另一個類別之內,甚至是某個方法之內;這種類別稱為內部類別(巢狀類別)
112/04/24 50112/04/24 50
Q13: 巢狀類別應用-成員類別1. class Ex2_14_1 {2. int i,j;3. private MyMember memb;4. class MyMember {5. int m,n,o;6. MyMember() { 7. i = 2; 8. Ex2_14_1.this.j = 4; 9. m = 12;10. this.n = 14; 11. MyMember.this.o = 16; }12. public int getO() { return o; } }13. public Ex2_14_1() {14. memb = new MyMember();15. System.out.println("m= "+memb.m + ","+"n= "+memb.n + ","+16. "o= "+memb.getO()); }17. public int getJ() { return j; }18. public static void main(String[] args) {19. Ex2_14_1 a = new Ex2_14_1();20. System.out.println("i= "+a.i +","+21. "j= "+a.getJ()); } }
112/04/24 51112/04/24 51
Q13: 巢狀類別應用-成員類別1. class MyClass {2. public class Pubmemb {3. private int i;4. public Pubmemb() { i = 5; }5. public int getI() { return i; }6. }7. private class Primemb{8. private int i;9. public Primemb() { i = 10; }10. public int getI() { return i; }11. }12. }13. class Ex2_14_2 {14. public static void main(String[] args) {15. MyClass a = new MyClass();16. MyClass.Pubmemb b = a.new Pubmemb();17. System.out.println("In Pubmemb i= "+b.getI());18. }19. }
112/04/24 52112/04/24 52
Q14: 巢狀類別應用-區域類別• 定義於方法內的類別,稱為區域內部類別• 使用區域類別時要注意其生存期,不在生存期範圍,是無法執行的• 區域類別在宣告時不宜前置
public 、 private 、 protected 等存取設定
112/04/24 53112/04/24 53
Q14: 巢狀類別應用-區域類別1. class Ex2_15_1 {2. int i;3. public Ex2_15_1() { 4. class MyLocal { 5. int i;6. public MyLocal(){7. Ex2_15_1.this.i = 5; 8. i= 10;9. }10. }11. MyLocal L = new MyLocal();12. System.out.println("i of Local: "+L.i);13. }14. public static void main(String[] args) {15. Ex2_15_1 m = new Ex2_15_1();16. System.out.println("i of Ex2_15_1: "+m.i);17. }18. }
112/04/24 54112/04/24 54
Q15: 繼承—父類別與子類別• Java 的繼承為「單一繼承」• 當一類別繼承自另一類別,前者為子類別 Sub
Class) ,後者為父類別 (Super Class)• 子類別繼承父類別所擁有之內涵• 單一繼承有先天的缺點,這個缺點由介面來補足,如此 Java 有多重繼承的優點,卻沒有多重繼承的缺點• Java 的繼承以類別為單位,使用 extends 關鍵字
112/04/24 55112/04/24 55
1. class MyNumber{2. private int number;3. public void setNumber(int i) {4. number = i;5. }6. public int getNumber() {7. return number;8. }9. }
10. class E extends MyNumber {}
11. class Ex3_1_1 {12. public static void main(String[] args) {13. E a = new E();14.15. a.setNumber(5);16. System.out.println("a=: "+a.getNumber());17. }18. }
+setNumber()+getNumber() : int
-number : intMyNumber
E
a : E
112/04/24 56112/04/24 56
Q16: 繼承-產生不同物件關係• 在繼承下,父類別或子類別各自所產生的新物件是各自獨立的,物件屬性亦是互不干擾的
112/04/24 57112/04/24 57
1. class MyNumber {2. private int number=5;3. public void setNumber(int i) { number = i; }4. public int getNumber() { return number; }5. }
6. class E1 extends MyNumber {} 7. class E2 extends MyNumber {}
8. class Ex3_1_2 {9. public static void main(String[] args) {10. E1 a1 = new E1();11. E2 a2 = new E2();12. a1.setNumber(10);13.14. System.out.println("The number of a1 is: "+a1.getNumber());15. System.out.println("The number of a2 is: "+a2.getNumber());16. }17. }
+setNumber()+getNumber() : int
-number : int = 5MyNumber
* *
E1 E2
a1 : E1
**
a2 : E2**
+setNumber()+getNumber() : int
-number : int = 5a1:E1:MyNumber
+setNumber()+getNumber() : int
-number : int = 5a2:E2:MyNumber
112/04/24 58112/04/24 58
Q17: 繼承-類別屬性• 類別屬性是指類別屬性之前置有 static 而成為類別屬性• 在繼承中,由父類別或子類別所產生的新物件,其類別屬性是指同一個變數;所以當任何一個物件更改了類別屬性值時,所有物件所看到的此物件值都是新值
112/04/24 59112/04/24 59
1. class MyNumber {2. private static int number=5;3. public void setNumber(int i) { number = i; }4. public int getNumber() { return number; }5. }
6. class E1 extends MyNumber {} 7. class E2 extends MyNumber {}8. class S extends E2 {}
9. class Ex3_1_3 {10. public static void main(String[] args) {11. E1 a1 = new E1();12. E2 a2 = new E2();13. S s = new S();14. s.setNumber(20);15. System.out.println("The number of a1 is: "+a1.getNumber());16. System.out.println("The number of a2 is: "+a2.getNumber());17. System.out.println("The number of s is: "+s.getNumber());18. }19. }
+setNumber()+getNumber() : int
-number : intMyNumber
E1
a1 : E1
E2
S
a2 : E2
s : S
+setNumber()+getNumber() : int
-number : int = 5a1:E1:MyNumber
+setNumber()+getNumber() : int
-number : int = 5a2:E2:MyNumber
+setNumber()+getNumber() : int
-number : int = 5s:S:E2:MyNumber
112/04/24 60112/04/24 60
Q18: 繼承• 子類別雖然有其本身自己之內容,但因是繼承自父類別,故亦具有父類別內容
112/04/24 61112/04/24 61
1. class MyNumber {2. private int number;3. public void setNumber(int i) { number = i; }4. public int getNumber() { return number; }5. }
6. class MyString extends MyNumber {7. private String string;8. public void setString(String s) { string = s; }9. public String getString() { return string; }10. }
11. class Ex3_1_4 {12. public static void main(String[] args) {13. MyString a = new MyString();14. a.setNumber(5);15. a.setString("I am in the SubClass");16.17. System.out.println("The number of a is: "+a.getNumber());18. System.out.println("The string of a is: "+a.getString());19. }20. }
+setNumber()+getNumber() : int
-number : intMyNumber
+setString()+getString() : char
-s : charMyString
number : ints : char
a : MyString
+setNumber()+getNumber() : int+setString()+getString() : char
-number : int-string : char
a:MyString:MyNumber
112/04/24 62112/04/24 62
Q19: Public/Protected/Private 存取限制在繼承中,變數前置 Public/Protected /Private之用法:• 當變數前置 public 時,該變數可被其他類別採用• 當變數前置 protected時,該變數可被同一包裹內之其他類別採用• 當變數前置 private時,該變數不得被其他類別採用;在繼承過程中,以 private 宣告的父類別之物件成員,不被子類別所繼承。不被繼承的成員存在子類別物件中的父類別物件內,只是子類別物件無權使用
112/04/24 63112/04/24 63
1. class myNumber {public int number;}
2. class E extends myNumber {3. public void setNumber(int i) {number = i;}4. public int getNumber() {return number;}5. }
6. class Ex3_2_1 {7. public static void main(String[] args) {8. E a = new E();9. a.setNumber(5);10. System.out.println("The number of a is: "+a.getNumber());11. }12. }
如果第1行的 public 改成 private 可不可以?
+number : intmyNumber
+setNumber()+getNumber() : int
E
number : inta : E
+setNumber()+getNumber() : int
+number : inta:E:myNumber
112/04/24 64112/04/24 64
Q20: super 與 this
• 關鍵字 super 為父類別之代名詞• 關鍵字 this 為自己本身類別之代名詞• 若子類別沒有重新定義屬性,且讓屬性也可以被繼承,則也可以使用 this取得父類別的屬性
112/04/24 65112/04/24 65
1. class myNumber {2. int number= 5;3. }
4. class E extends myNumber{5. int number= 10;6. public int getsuperNumber() {return super.number;}7. public int getthisNumber() {return this.number;}8. }
9. class Ex3_3_1 {10. public static void main(String[] args) {11. E a = new E();12. 13. System.out.println("The myNumber_number of a is: "14. +a.getsuperNumber());15. System.out.println("The E_number of a is: "+a.getthisNumber());16. }17. }
#number : int = 5myNumber
+getsuperNumber() : int+getthisNumber() : int
#number : int = 10E
number : inta : E
+getsuperNumber() : int+getthisNumber() : int
+super.number : int-this.number
a:E:myNumber
112/04/24 66112/04/24 66
Q21: super() 用於建構子• 關鍵字 super() 可視為父類別之建構子
112/04/24 67112/04/24 67
1. class myNumber {2. private int number;
3. myNumber (int number) {this.number = number;}4. public int getNumber() { return number; }5. }
6. class E extends myNumber {7. E() {super(5);}8. }
9. class Ex3_3_2 {10. public static void main(String[] args) {11. E a = new E();
12. System.out.println("number= "+a.getNumber());13. }14. }
+myNumber()+getNumber() : int
-number : intmyNumber
+E()
E
number : inta : E
+myNumber()+getNumber() : int+E()
-numbera:E:myNumber
112/04/24 68112/04/24 68
Q22: super()
• 子類別繼承父類別時,系統將會於子類別的第一列,自加上一行 super() ,即自動呼叫父類別之建構子• 建構子是不被繼承的• 在建立子類別物件時,父類別的預設建構子會先被呼叫,接著子類別的建構子才會被呼叫• This() 和 super()只能擇一使用,並且必須出現在建構子的第一個敘述
112/04/24 69112/04/24 69
1. class A {2. A() { System.out.println("A's constructor");}3. }
4. class B extends A {5. B() { System.out.println("B's constructor");}6. }
7. class C extends B {8. C() { System.out.println("C's constructor");}9. }
10. class Ex3_3_3 {11. public static void main(String[] args) {12. C c = new C();13. }14. }
+A()
A
+B()
B
+C()
C
c
+A()+B()+C()
c:C:B:A
112/04/24 70112/04/24 70
Q23: final 之應用• 當類別前置 final時,該類別將不允許被繼承
112/04/24 71112/04/24 71
1. final class myNumber {2. int number= 5;3. }
4. class E extends myNumber{5. int number= 10;6. public int getsuperNumber() {return super.number;}7. public int getthisNumber() {return this.number;}8. }
9. class Ex3_4_1 {10. public static void main(String[] args) {11. E a = new E();12. 13. System.out.println("The myNumber_number of a is: "14. +a.getsuperNumber());15. System.out.println("The E_number of a is: "+a.getthisNumber());16. }17. }
112/04/24 72112/04/24 72
Q24: abstract 之應用• 類別前加置 abstract ,該類別為抽象類別• 抽象類別不得用於產生物件
112/04/24 73112/04/24 73
1. abstract class myNumber {2. private int number = 5;3. public int getNumber() { return number; }4. }
5. class Ex3_5_1 {6. public static void main(String[] args) {7. myNumber a = new myNumber();8. System.out.println(a.getNumber());9. }10. }
+getNumber() : int-number : int = 5
myNumber
a
+getNumber() : int-number : int
a:myNumber
112/04/24 74112/04/24 74
Q25: 抽象方法• 方法若前置 abstract ,即所謂抽象方法• 抽象方法沒有程式碼內容• 抽象方法一定是會被覆蓋的方法• 定義抽象方法時,不能同時使用
final 、 static 、 private 宣告
112/04/24 75112/04/24 75
1. abstract class myNumber {2. public int number = 5 ;3. public abstract int getNumber(); 4. }
5. class E extends myNumber {6. public int getNumber() {return number;}7. }
8. class Ex3_5_3 {9. public static void main(String[] args) {10. E a = new E();11. System.out.println("the number of a= "+a.getNumber());12. }13. }
+getNumber() : int+number : int = 5
myNumber
a
+getNumber() : int
E
+getNumber() : int-number : inta:E:myNumber
112/04/24 76112/04/24 76
Q26: 抽象類別之應用• 抽象類別用於被繼承,再由繼承之類別產生新物件• 只要有一個方法(或以上)定義為抽象方法,則該類別為抽象類別• 於繼承類別時,如果父類別中有抽象方法時,子類別中必有方法會完成抽象方法處理程序(程式),才可以建立物件• 抽象類別的目的,主要是「制定固定的訊息接收管道」
112/04/24 77112/04/24 77
1. abstract class myNumber {2. private int number = 5;3. public int getNumber() { return number; }4. }
5. class E extends myNumber {}
6. class Ex3_5_2 {7. public static void main(String[] args) {8. E a = new E();9. System.out.println("the number of a= "+a.getNumber());10. }11. }
+getNumber() : int-number : int = 5
myNumber
a
E
+getNumber() : int-number : inta:E:myNumber
112/04/24 78112/04/24 78
Q27: interface• 所謂介面,即是前置 interface ;是 Java保有多重繼承特性的機制• 介面內之方法,均是抽象方法(無程式碼)• 介面不得用於產生新物件,介面是用於被實作
( implement) 的• 當介面被類別承作時,須使用關鍵字 implements ,其他之繼承,要使用關鍵字 extends• 一個類別可同時承作一個(含)以上之介面,且使用介面內之方法時,在方法中必須加置程式碼• 介面之承作,僅約定繼承之行為名稱,並不約束繼承行為;一般類別之繼承,是繼承父類別之行為
112/04/24 79112/04/24 79
1. interface myITF1 {public void f();}
2. interface myITF2 {public void g();}
3. class A implements myITF1,myITF2 {4. public void f() {System.out.println("In myITF1");}5. public void g() {System.out.println("In myITF2");}6. }
7. class Ex3_6_1 {8. public static void main(String[] args) {9. A a = new A();10. a.f();11. a.g();12. }13. }
+f()
<<interface>>myITF1
+g()
<<interface>>myITF2
+f()+g()
A
a : A
+f()+g()
a:A:myITF1, myITF2
112/04/24 80112/04/24 80
1. interface myITF1 {public void f();}
2. class myNumber {3. public void g() {System.out.println("In myNumber");}4. }
5. class A extends myNumber implements myITF1 {6. public void f() {System.out.println("In myITF1");}
7. }
8. class Ex3_6_2 {9. public static void main(String[] args) {10. A a = new A();11. a.f();12. a.g();13. }14. }
+f()
<<interface>>myITF1
+g()
myNumber
+f()
A
a : A
+f()+g()
a:A:myNumber myITF1
112/04/24 81112/04/24 81
Q28: 物件的型別轉換• 子類別物件也屬於父類別物件• 使用父類別的參照變數指向子類別的物件
時 ,無法使用該參照變數取用子類別定義的成員
112/04/24 82112/04/24 82
1. Class EX8_122. {3. public static void main (String [] args)4. {5. Fish a = new Fish();6. Vertebrate b = new Fish();7. Animal c = new Fish();8. // Fish d = new Vertebrate(); //錯誤9. System.out.println(“a=“ + a);10. System.out.println(“b=“ + b);11. System.out.println(“c=“ + c);12. }13. }14. Class Animal{ }15. Class Vertebrate extends Animal { }16. Class Fish extends Vertebrate { }
輸出結果是 : 三個不同的位址 , 而其中資料架構是以 fish, 但是父類別的參照變數不可以使用子類別定義的成員
112/04/24 83112/04/24 83
1. class myClass1 {2. public void f() {System.out.println("In f of myClass1");3. }4. }
5. class myClass2 extends myClass1 {6. public void g() {System.out.println("In g of myClass2");7. }8. }
9. class Ex3_7_2 {10. public static void main(String[] args) {11. myClass1 a = new myClass2();12. a.f();13. }14. }
+f()
myClass1
+g()
myClass2
a : myClass2
+myClass1.f()
a:myClass2:myClass1
112/04/24 84112/04/24 84
1. class myClass1 {2. public void f() {System.out.println("In f of myClass1");3. }4. }
5. class myClass2 extends myClass1 {6. public void g() {System.out.println("In g of myClass2");7. }8. }
9. class Ex3_7_2 {10. public static void main(String[] args) {11. myClass1 a = new myClass2();12. a.g();13. }14. }
+f()
myClass1
+g()
myClass2
a : myClass2
+myClass1.f()
a:myClass2:myClass1
112/04/24 85112/04/24 85
Q29: 方法的覆蓋 (overridung)
• 子類別可以重新定義物件屬性,也可以重新定義物件方法,重新定義物件方法稱為方法的覆蓋• 在方法覆蓋時,下列各項必須和父類別定義的方法相同:
– 方法的回傳型別– 方法名稱– 形式參數列中的型別及順序
• 覆蓋舊方法時,新定義的方法可以呼叫舊方法• 使用 final 宣告的父類別之物件方法不能被覆蓋
112/04/24 86112/04/24 86
1. Class EX8_172. { public static void main(String [] args)3. { new WolfDog().bark();4. new Doberman.bark();5. new Dog().bark();6. }7. }8. Class Dog 9. { void bark() {System.out.print(“汪汪” ); } }10. Class WolfDog extends Dog11. { void bark() { System.out.println(“ 汪 ~ 汪 ~ 嗚 ~”); } }12. Class Doberman extends Dog13. { void bark() 14. { super.bark();15. System.out.println(“~汪汪汪 ~”);16. }17. }
112/04/24 87112/04/24 87
Q30: 多重形態( polymorphism )
• 多型是指「使用相同的訊息呼叫,可以進行不同的功能操作」• 若子類別物件轉換成父類別物件,呼叫其方法時,若該方法為子類別定義的方法,則不允許被呼叫;若該方法被子類別覆蓋,則呼叫子類別的覆蓋方法。• 不論參照的型別為何,呼叫方法時,呼叫最新的覆蓋方法• 在異質集合中,若呼叫父類別被覆蓋的方法,則每個方法的反應會因為覆蓋的關係而有所不同
112/04/24 88112/04/24 88
1. class myClass1 {2. public void f() {System.out.println("In myClass1");3. }4. }
5. class myClass2 extends myClass1 {6. public void f() {System.out.println("In myClass2");7. }8. }
9. class Ex3_7_1 {10. public static void main(String[] args) {11. myClass1 a = new myClass2();12. a.f();13. }14. }
+f()
myClass1
+f()
myClass2
a : myClass2
+myClass2.f()+myClass1.f()
a:myClass2:myClass1
112/04/24 89112/04/24 89
1. Class EX8_192. { public static void main(String [] args)3. { Dog[] d = new Dog[3];4. d[0] = new WolfDog();5. d[1] = new Doberman();6. d[2] = new Dog();7. for (int I=0; I<d.length; I++)8. d[I].bark();9. }10. }11. Class Dog 12. { void bark() {System.out.print(“汪汪” ); } }13. Class WolfDog extends Dog14. { void bark() { System.out.println(“ 汪 ~ 汪 ~ 嗚 ~”); } }15. Class Doberman extends Dog16. { void bark() 17. { super.bark();18. System.out.println(“~汪汪汪 ~”);19. }20. }