若創建一個內部類,然後從封裝類繼承,並重新定義內部類,那麼會出現什麼情況呢?也就是說,我們有可能覆蓋一個內部類嗎?這看起來似乎是一個非常有用的概念,但“覆蓋”一個內部類——好象它是外部類的另一個方法——這一概念實際不能做任何事情:
//: BigEgg.java // An inner class cannot be overriden // like a method class 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 class class 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()的被覆蓋版本。