Download
slide1 n.
Skip this Video
Loading SlideShow in 5 Seconds..
Ch07 巢狀類別 PowerPoint Presentation
Download Presentation
Ch07 巢狀類別

Ch07 巢狀類別

234 Vues Download Presentation
Télécharger la présentation

Ch07 巢狀類別

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

  1. Ch07 巢狀類別 物件導向程式設計(2)

  2. 巢狀類別-說明 • 在Java類別之中可以擁有其它類別的成員,這種類別稱為「巢狀類別」(Nested Classes)。 • 巢狀類別強調類別之間的關係,成員類別稱為「內層類別」(Inner Classes)。 • 例如:Employee巢狀類別擁有成員類別Phone的內層類別,Employee是巢狀類別的「外層類別」(Enclosing Class)。

  3. 巢狀類別-圖例 • Employee物件的圖例,如下圖所示:

  4. 巢狀類別-範例 class Employee // Employee外層類別 { ………… class Phone // Phone內層類別 { …………… } ………… }

  5. 巢狀類別-特點 • 巢狀類別強調類別間的關係,例如:員工擁有連絡電話的資料,所以Phone類別屬於Employee類別的一部分。 • 巢狀類別的內層類別也屬於外層類別的成員,所以其它成員可以存取或呼叫內層類別的成員變數和方法,就算是宣告成private的都一樣可以存取,反之內層類別的方法也可以直接存取其它成員變數和呼叫成員方法。 • 在Java程式檔案只允許一個宣告成public的類別,如果巢狀類別宣告成public,內層類別也能夠擁有public的存取權限。

  6. class Ch06_03 { public static void main(String [] args) { Employee0603 e1 = new Employee0603("ToTo", "07-111-1111", "0911-111-111"); System.out.println("呼叫物件方法printEmployee"); e1.printEmployee(); System.out.println("呼叫e1物件中的list物件的方法printPhone"); e1.list.printPhone(); System.out.println("呼叫e1物件中的list物件的屬性home和cell"); System.out.println("電話(住家): " + e1.list.home); System.out.println("行動電話: " + e1.list.cell); } } class Employee0603 { String name; Phone0603 list; Employee0603(String name, String home, String cell) { this.name = name; list = new Phone0603(home, cell); } void printEmployee() { System.out.println("在Employee類別內"); System.out.println("===== 員工 ====="); System.out.println("姓名: " + name); System.out.println("利用呼叫內部物件的屬性來取得電話 ==>"); System.out.println("電話(住家): " + list.home); System.out.println("行動電話: " + list.cell); System.out.println("利用呼叫內部物件的方法printPhone來取得電話 ==>"); list.printPhone(); } String getName() { return name; } class Phone0603 { String home; String cell; public Phone0603(String phone1, String phone2) { home = phone1; cell = phone2; } void printPhone() { System.out.println("利用呼叫外部的物件方法==>"); System.out.println("姓名: " + getName()); System.out.println("電話(住家): " + home); System.out.println("行動電話: " + cell); } } } 範例1

  7. 內層類別的使用-範例(1/2) • 例如:Customer巢狀類別,如下所示: class Customer // Customer外層類別 { ……… class Address // Address內層類別 { ……… }

  8. 內層類別的使用-範例(2/2) • 在Java程式需要先建立Customer物件,才能建立Address物件,如下所示: Customer c1 = new Customer(“ToTo", 29001234); Customer.Address home = joe.new Address(); • 上述程式碼先使用new運算子建立joe參考的Customer物件,接著使用Customer.Address宣告物件變數home,然後使用joe.new建立Address物件,最後指定成員變數值,如下所示: home.address = "台北縣五股鄉成泰路一段"; home.zip = 248;

  9. class Ch06_04 { public static void main(String [] args) { Employee0604 e1 = new Employee0604("ToTo"); Employee0604.Phone0604 p1 = e1.new Phone0604("07-111-1111", "0911-111-111"); System.out.println("呼叫物件方法printEmployee"); e1.printEmployee(); System.out.println("呼叫p1物件中的方法printPhone"); p1.printPhone(); System.out.println("呼叫p1物件中的屬性home和cell"); System.out.println("電話(住家): " + p1.home); System.out.println("行動電話: " + p1.cell); } } class Employee0604 { String name; Employee0604(String name) { this.name = name; } void printEmployee() { System.out.println("在Employee類別內"); System.out.println("===== 員工 ====="); System.out.println("姓名: " + name); } String getName() { return name; } class Phone0604 { String home; String cell; Phone0604(String phone1, String phone2) { home = phone1; cell = phone2; } void printPhone() { System.out.println("利用呼叫外部的物件方法==>"); //System.out.println("姓名: " + getName()); System.out.println("電話(住家): " + home); System.out.println("行動電話: " + cell); } } } 範例2

  10. 巢狀類別(內部類別) • 位於另一個類別之內的類別稱之為內部類別(inner classes),或稱為巢狀類別(nested classes) • 靜態內部類別 • 非靜態內部類別 • 區域內部類別

  11. 靜態內部類別 • 使用static修飾字宣告的內部類別,稱為靜態內部類別(static inner classes)。 • 靜態內部類別和類別內其它靜態成員一樣,都屬類別所有,所以類別方法可以直接使用靜態內部類別建立物件。 • 若某個類別欲使用另一個類別的靜態內部類別時,必須以點運算子(dot operator)指明靜態內部類別所屬的類別,才可使用

  12. 內層類別的使用-說明 • 巢狀類別的內層類別屬於外層類別的成員物件,所以不能宣告成static(???)的類別變數和方法,而且只有外層類別的物件存在時,內層類別才會存在。

  13. class Ch06_05 { public static void main(String [] args) { Employee0605 e1 = new Employee0605("ToTo", "07-111-1111", "0911-111-111"); System.out.println("呼叫物件方法printEmployee"); e1.printEmployee(); System.out.println("呼叫e1物件中的list物件的方法printPhone"); e1.list.printPhone(); System.out.println("呼叫e1物件中的list物件的屬性home和cell"); System.out.println("電話(住家): " + e1.list.home); System.out.println("行動電話: " + e1.list.cell); } } class Employee0605 { String name; Phone0605 list; Employee0605(String name, String home, String cell) { this.name = name; list = new Phone0605(home, cell); } void printEmployee() { System.out.println("在Employee類別內"); System.out.println("===== 員工 ====="); System.out.println("姓名: " + name); System.out.println("利用呼叫內部物件的屬性來取得電話 ==>"); System.out.println("電話(住家): " + list.home); System.out.println("行動電話: " + list.cell); System.out.println("利用呼叫內部物件的方法printPhone來取得電話 ==>"); list.printPhone(); } String getName() { return name; } static class Phone0605 { String home; String cell; public Phone0605(String phone1, String phone2) { home = phone1; cell = phone2; } void printPhone() { System.out.println("利用呼叫外部的物件方法==>"); //System.out.println("姓名: " + getName()); System.out.println("電話(住家): " + home); System.out.println("行動電話: " + cell); } } } 範例3

  14. class Ch06_06 { public static void main(String [] args) { Employee0606 e1 = new Employee0606("ToTo"); Employee0606.Phone0606 p1 = new Employee0606.Phone0606("07-111-1111", "0911-111-111"); System.out.println("呼叫物件方法printEmployee"); e1.printEmployee(); System.out.println("呼叫p1物件中的方法printPhone"); p1.printPhone(); System.out.println("呼叫p1物件中的屬性home和cell"); System.out.println("電話(住家): " + p1.home); System.out.println("行動電話: " + p1.cell); } } class Employee0606 { String name; Employee0606(String name) { this.name = name; } void printEmployee() { System.out.println("在Employee類別內"); System.out.println("===== 員工 ====="); System.out.println("姓名: " + name); } String getName() { return name; } static class Phone0606 { String home; String cell; Phone0606(String phone1, String phone2) { home = phone1; cell = phone2; } void printPhone() { System.out.println("利用呼叫外部的物件方法==>"); //System.out.println("姓名: " + getName()); System.out.println("電話(住家): " + home); System.out.println("行動電話: " + cell); } } } 範例4

  15. 非靜態內部類別 • 沒有static修飾的內部類別稱為非靜態內部類別(non-static inner classes)。 • 非靜態內部類別和其它物件成員一樣,都必須建立物件才能使用。 • 以非靜態內部類別所建立的實體,實際上都必須與外部類別的實體結合在一起。因為沒有外部類別所建立的實體,就沒有非靜態內部類別的建構子

  16. 區域內部類別 • 定義於方法內的類別,稱為區域內部類別(local inner classes)。 • 區域內部類別不屬於外部類別的類別成員,也不是物件成員,其性質就像區域變數一樣,只能在定義的方法內使用,而且必須先定義才能使用。 • 區域內部類別不使用public、protected、private和static等修飾字。 • 區域內部類別可以取用外部方法中以final宣告的變數,不是以final宣告的變數不能取用

  17. 修飾字(1/3) • 存取權限修飾字

  18. 修飾字(2/3) • 被修飾者可用的存取權限修飾字

  19. 修飾字(3/3) • 被修飾者可用的修飾字

  20. 類屬(is a) 和擁有(has a) class A extends B implements C, D { E e; F f; A(){ e = new E(); f = new F(); } } • 類屬(is a)關係為物件和類別(或介面)之間的關係。A型別的物件可以類屬於類別A、類別B、介面C和介面D。 • 擁有(has a)關係為物件和物件之間的關係。A型別的物件擁有E型別的物件及F型別的物件。

  21. 內部類別與繼承 父類別包含內部類別時,子類別也可以繼承內部類別,如同繼承其它成員一樣。 內部類別可以有繼承關係,而且沒有特別限制。

  22. 範例5:內部類別繼承其它類別 • class EX8_23 • { //靜態內部類別,繼承Super23 • static class Sub1 extends Super23 {} • //一般內部類別,繼承Super23 • class Sub2 extends Super23 {} • public static void main(String [] args) • { System.out.println( new EX8_23.Sub1() ); • System.out.println( new EX8_23().new Sub2() ); • //區域類別,繼承Super23 • class Sub3 extends Super23 {} • System.out.println( new Sub3() ); } } • //Super23類別定義 • class Super23 • { Super23() • { System.out.print("Super23建構子被呼叫了\t"); } }

  23. 匿名類別 匿名類別(Anonymous classes)是區域內部類別的一種,顧名思義匿名類別沒有名稱,所以也不能定義建構子。 匿名類別的目的只是要建立一個物件,物件建立之後就不會再使用該類別。 匿名類別常當作覆蓋或實作抽象方法之用。

  24. 匿名類別 匿名類別的功能就是只建立一個物件,所以類別主體的定義和建立物件是一氣呵成的。 繼承類別建立匿名類別: new 父類別(參數列) { // 類別主體 } 實作介面建立匿名類別: new 介面() { // 類別主體 }

  25. 範例6:匿名類別 • class EX8_25 • { public static void main(String [] args) • { Sup s = new Sup() • { //實體初始化區塊 • { System.out.println(this); } • void m() //覆蓋方法 • { System.out.println(“覆蓋過的m方法”); } • void n() //匿名類別自訂的方法 • { System.out.println(“自訂的n方法”); } • }; • s.m(); • //s.n(); //錯誤 • } • } • //Sup類別定義 • class Sup • { void m() • { System.out.println("Sup實體的m方法"); • } • }