2012-10-23 63 views
8

我無法理解繼承在Java中是如何工作的,當內部類是存在的。我目前正在研究一些子類需要稍微改變父類內部類的功能的東西。我在下面提出了一個更簡單,更具代表性的例子。如何Java繼承工作時內部類涉及

我希望這段代碼打印「我是ChildClass.InnerClass」,但它打印 「我是ParentClass.InnerClass」。爲什麼是這樣?另外,如果我改變主 obj的對象是類型ChildClass的則輸出變爲「我是一個ChildClass.InnerClass」。爲什麼是這樣?

一般情況下,是什麼改變對象的父類的內部對象的行爲的推薦的方法?

class InnerClassTest { 
    //----------------------------------------------------------------------- 
    // PARENT CLASS 
    class ParentClass { 
     public ParentClass() { 
     x = new InnerClass(); 
     } 

     InnerClass x; 

     class InnerClass { 
     public void speak() { 
      System.out.println("I am a ParentClass.InnerClass"); 
     } 
     } 
    } 

    //----------------------------------------------------------------------- 
    // CHILD CLASS 
    class ChildClass extends ParentClass { 
     public ChildClass() { 
     x = new InnerClass(); 
     } 

     InnerClass x; 

     class InnerClass extends ParentClass.InnerClass { 
     public void speak() { 
      System.out.println("I am a ChildClass.InnerClass"); 
     } 
     } 
    } 

    //----------------------------------------------------------------------- 
    // MAIN 
    public static void main(String[] args) { 
     ParentClass obj = (new InnerClassTest()).new ChildClass(); 
     obj.x.speak(); 
    } 
} 

回答

6

變量不是方法所「重寫」的。

在您的電話中,您期望xChild的一個,但它不是因爲x是一個變量,而不是一個方法。

但要注意:你的引用類型爲ParentClass所以obj.x指向ParentClassInnerClass屬性,即使背後parentClass真正的實例是ChildClass

爲了顯示你的預期句話,你必須類型引用更改爲ChildClass

public static void main(String[] args) { 
     ChildClass obj = (new InnerClassTest()).new ChildClass(); 
     obj.x.speak(); 
} 

爲了更好地理解這個概念,試圖在這兩個ParentClassChildClass類來定義的方法:

public InnerClass getInnerClass(){ 
    return x; 
} 

,並x私人。

,使「覆蓋的概念」適用。

你最終的呼叫會在這種情況下:

ParentClass obj = (new InnerClassTest()).new ChildClass(); 
obj.getInnerClass().speak(); 

要改變內部類的行爲,認爲模板方法模式或更好的:策略模式(因爲更尊重的DIP)

3

刪除重複宣告

InnerClass x; 

FR om兒童班。所以,你將只有一個x,並將在子類的構造函數中重新分配。這意味着一個x(指的是在ctor中創建的對象)。

它隱藏在一個父類。這就是爲什麼你最終有兩個領域,指的是兩個不同的對象。並且由於靜態(編譯時或提前)的變量的情況下結合,

ParentClass obj; 
//obj.x means the x in parent 

ChildClass obj; 
//obj.x means the x in child 
+0

'ParentClass obj; //obj.x表示孩子中的x你的意思是ChildClass obj; – exexzian

+0

@sansix:的確如此。感謝編輯。 –

+0

+1的解決方案 – exexzian

1

在一般情況下,是什麼改變了 對象的行爲的推薦方法父類的內部對象?

我建議使用一個不太複雜的設計開始。一個子類應該通過重寫它的方法來修改父類的行爲,所以我只需要添加一些工廠方法newInnerClass()來覆蓋這個依賴關係的創建,並在類層次結構的頂部管理這個對象。

這會比你的建議更靈活,因爲newInnerClass()可以實例化一個只要有正確接口就定義的類。