2017年8月12日 星期六

Chapter 10: 內隱類別

撰寫inner classes
  • 若想要在outer class的non-static method之外產生一個inner class物件,須以OuterClassName.InnerClassName的形式指定該物件的型別。
public class Parcel2 {
     class Contents {
         private int i = 11;
         public int value() { return i; }
     }

     // 一般會在outer class中建立method來產生inner class物件
     public Contents contents() {
         return new Contents();
     }

     public static void main(String[] args) {
         Parcel2 q = new Parcel2();
         // Defining references to inner classes:
         Parcel2.Contents c = q.contents();
     }

  • outer class又可稱為enclosing class
  • inner class可以存取enclosing class的所有成員,就好像inner class自己擁有這些成員一樣。
  • non-static的inner class會自動記錄一個reference指向enclosing class的某個物件,後者就是此inner class物件的製造者。也就是一定會先有enclosing class物件才有辦法產生inner class物件。

使用.this及.new
  • 若想在inner class中產生指向outer class物件的reference,可以使用OuterClassName.this
public class DotThis {
     void f() { System.out.println("DotThis.f()"); }
     public class Inner {
         public DotThis outer() {
             return DotThis.this;
         }
     }
     public Inner inner() { return new Inner(); }
     public static void main(String[] args) {
         DotThis dt = new DotThis();
         DotThis.Inner dti = dt.inner();
         dti.outer().f();
     }
}

  • 若是想用outer class物件來產生inner class物件,可使用.new
public class DotNew {
     public class Inner {}
     public static void main(String[] args) {
         DotNew dn = new DotNew();
         DotNew.Inner dni = dn.new Inner();
     }
}

位於methods和scopes內的inner class
  • 基於兩個理由可能會想這樣做
    • 想實作某個interface,使你可產生並回傳其reference。
    • 希望在解決方案中設計某個class,又不希望此class給外界使用。
public class Parcel5 {
     public Destination destination(String s) {
         class PDestination implements Destination {
             private String label;
             private PDestination(String whereTo) {
                 label = whereTo;
             }
             public String readLabel() { return label; }
         }
         return new PDestination(s);
     }
     public static void main(String[] args) {
         Parcel5 p = new Parcel5();
         Destination d = p.destination("Tasmania");
     }
}

匿名的inner class
public class Parcel7 {
     public Contents contents() {
         return new Contents() { // Insert a class definition
             private int i = 11;
             public int value() { return i; }
         }; // Semicolon required in this case
     }
     public static void main(String[] args) {
         Parcel7 p = new Parcel7();
         Contents c = p.contents();
     }
}
  • 產生某個匿名class的物件,此匿名class是繼承自Contents。
  • new回傳的reference會被自動向上轉型為Contents reference。

巢狀類別
  • static的inner class被稱為nested class
  • nested class意味著:
    • 生成nested class的物件時不需要outer class的物件了。
    • 無法在nested class的物件中存取outer class的non-static物件。
    • 可擁有static data及nested class。

為什麼需要inner class
  • 若你想同時繼承多個抽象或具象的class,必須用inner class來做到。

繼承inner class
  • 繼承inner class時,指向outer class物件的reference必須被初始化。


class WithInner {
     class Inner {}
}
public class InheritInner extends WithInner.Inner {
     //! InheritInner() {} // Won’t compile
     InheritInner(WithInner wi) {
         wi.super();
     }
     public static void main(String[] args) {
         WithInner wi = new WithInner();
         InheritInner ii = new InheritInner(wi);
     }
}

沒有留言:

張貼留言