1. 程式人生 > >內部類的繼承從而實現對父類的private欄位的引用

內部類的繼承從而實現對父類的private欄位的引用

子類

public class SubClass extends SuperClass.InnerClass {
	SuperClass superClass;
	public SubClass (SuperClass superClass){
		superClass.super();   //由於內部類構建器必須同封裝類物件的一個控制代碼聯絡到一起,
                                                     //所以從一個內部類繼承的時候這裡建立一個控制代碼
		this.superClass = superClass;
	}
	
	public void show(){
		System.out.println(this.returnPrivates());
	}
}

父類: 有一個private 的欄位privates

public class SuperClass {
	private String privates = "know by Super itsself";
	
	public class InnerClass {
				
		public String returnPrivates(){
			return privates;
		}
	}
}

  測試類:

public class Test {
	public static void main(String[] args) {
		SubClass sub = new SubClass (new SuperClass());
		sub.show();
	}

}
從內部類繼承
由於內部類構建器必須同封裝類物件的一個控制代碼聯絡到一起,所以從一個內部類繼承的時候,情況會稍微變得有些複雜。這兒的問題是封裝類的“祕密”控制代碼必須獲得初始化,而且在衍生類中不再有一個預設的物件可以連線。解決這個問題的辦法是採用一種特殊的語法,明確建立這種關聯:

    //: InheritInner.java// Inheriting an inner classclass 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);   }} ///:~


從中可以看到,InheritInner只對內部類進行了擴充套件,沒有擴充套件外部類。但在需要建立一個構建器的時候,預設物件已經沒有意義,我們不能只是傳遞封裝物件的一個控制代碼。此外,必須在構建器中採用下述語法:
enclosingClassHandle.super();
它提供了必要的控制代碼,以便程式正確編譯。

7.6.7 內部類可以覆蓋嗎?
若建立一個內部類,然後從封裝類繼承,並重新定義內部類,那麼會出現什麼情況呢?也就是說,我們有可能覆蓋一個內部類嗎?這看起來似乎是一個非常有用的概念,但“覆蓋”一個內部類——好象它是外部類的另一個方法——這一概念實際不能做任何事情:

    //: BigEgg.java// An inner class cannot be overriden // like a methodclass Egg {  protected class Yolk {    public Yolk() {       System.out.println("Egg.Yolk()");     }   }  private Yolk y;  public Egg() {     System.out.println("New Egg()");     y = new Yolk();   }}public class BigEgg extends Egg {  public class Yolk {    public Yolk() {       System.out.println("BigEgg.Yolk()");     }   }  public static void main(String[] args) {    new BigEgg();   }} ///:~


預設構建器是由編譯器自動合成的,而且會呼叫基礎類的預設構建器。大家或許會認為由於準備建立一個BigEgg,所以會使用Yolk的“被覆蓋”版本。但實際情況並非如此。輸出如下:
New Egg()
Egg.Yolk()
這個例子簡單地揭示出當我們從外部類繼承的時候,沒有任何額外的內部類繼續下去。然而,仍然有可能“明確”地從內部類繼承:

    //: BigEgg2.java// Proper inheritance of an inner classclass Egg2 {  protected class Yolk {    public Yolk() {       System.out.println("Egg2.Yolk()");     }    public void f() {       System.out.println("Egg2.Yolk.f()");     }   }  private Yolk y = new Yolk();  public Egg2() {     System.out.println("New Egg2()");   }  public void insertYolk(Yolk yy) { y = yy; }  public void g() { y.f(); }}public class BigEgg2 extends Egg2 {  public class Yolk extends Egg2.Yolk {    public Yolk() {       System.out.println("BigEgg2.Yolk()");     }    public void f() {       System.out.println("BigEgg2.Yolk.f()");     }   }  public BigEgg2() { insertYolk(new Yolk()); }  public static void main(String[] args) {     Egg2 e2 = new BigEgg2();     e2.g();   }} ///:~


現在,BigEgg2.Yolk明確地擴充套件了Egg2.Yolk,而且覆蓋了它的方法。方法insertYolk()允許BigEgg2將它自己的某個Yolk物件上溯造型至Egg2的y控制代碼。所以當g()呼叫y.f()的時候,就會使用f()被覆蓋版本。輸出結果如下:
Egg2.Yolk()
New Egg2()
Egg2.Yolk()
BigEgg2.Yolk()
BigEgg2.Yolk.f()
對Egg2.Yolk()的第二個呼叫是BigEgg2.Yolk構建器的基礎類構建器呼叫。呼叫
g()的時候,可發現使用的是f()的被覆蓋版本。