2012-05-26 55 views
0

具體來說,爲什麼在父類和子類中聲明的變量在傳遞給參數爲父類的方法的子類實例中不可見?在Java中,爲什麼在父類和子類中聲明的變量在子類的實例中不可見?

這是一個令我困惑的問題的簡單例子。有三個類,一個父類和兩個子類。該班有一個Foo對象作爲一個字段,這個靜態類型的工廠方法:

class Parent { 
    public Foo myFoo; 

    public static ThinChild createThinChild(Foo someFoo) { 
     ThinChild thinChild = new ThinChild(someFoo); 
     return thinChild; 
    } 

    public Foo getFoo() { 
     return myFoo; 
    } 
} 

class ThinChild extends Parent { 
    public Foo myFoo; 

    public ThinChild(Foo someFoo) { 
     myFoo = someFoo; 
    } 
} 

class ThickChild extends Parent { 
    public Foo myFoo; 

    public ThickChild(Foo someFoo) { 
     myFoo = someFoo; 
    } 
} 

現在考慮這個處理程序類:

class ChildHandler { 
    private void doSomethingToThinChild(ThinChild thinChild) { 
     assert(thinChild.getFoo() != null); 
     doSomethingToAllChildren(thinChild); 
    } 

    private void doSomethingToAllChildren(Parent thinOrThickChild) { 
     assert(thinOrThickChild.getFoo() != null); 
    } 
} 

當我打電話doSomethingToThinChild,斷言通過。但在方法doSomethingToAllChildren中,斷言失敗。這不是我所期望的。

此外,如果我在Parent類中爲我的ThinChild類添加了相同的確切getFoo方法,則斷言現在可用。這解決了我眼前的問題,但對我來說似乎不受歡迎,因爲我現在在每個子類中保持相同的代碼,我只是希望將其保留在父代中。

我的實際情況有點複雜,但我希望我已經記錄了所有相關的細節。假設我有,是否有解釋爲什麼這會是預期的行爲?

有可能是我的實際代碼中有一個額外的複雜因素,我沒有在這裏表示。但是我首先想確認我對Java中的類繼承的理解是正確的。

謝謝。

+1

你是說'class ThinChild extends Parent'? – alaster

+0

您不需要在嵌套類中聲明 'public Foo myFoo;'。 myFoo已經有 – alaster

+1

這三個類是完全不相關的。沒有課程擴展任何其他課程。處理程序不會編譯。 –

回答

1

刪除public Foo myFoo。在嵌套類中,該字段從父類繼承。你不能改變它,因爲你有兩個同名的變量。所以JVM初始化了範圍較小的變量。

另外的好辦法是在父母創建的構造函數:

public Parent(Foo someFoo) { 
    myFoo = someFoo; 
} 

然後調用它的子類:

public ThinChild(Foo someFoo) { 
    super(someFoo); 
} 
+0

刪除子類中聲明的字段解決了我的問題。謝謝。但我不明白爲什麼它很重要。你能否更新答案來強調這一點,並幫助我理解爲什麼它很重要,如果可能的話? – klenwell

+0

變量myFoo在嵌套類中不可見,因爲您有兩個具有相同名稱的變量,所以無法更改它。所以JVM初始化變量的範圍較小 – alaster

+0

謝謝@alaster。編輯你的答案,包括你的意見,並選擇它。 – klenwell

1

myFoo是直接子類可見,你只需要限定它與「super.myFoo」。儘管這隻能在連鎖店上升1級。所以如果ThinChild的子類ThinnerChild也帶有一個myFoo,那麼您無法訪問父類中的「myFoo」實例。這個想法是,你應該能夠覆蓋你的父母的行爲,但你不應該能夠覆蓋你的父母(因此爲什麼像super.super是不允許的)。這就是說,刪除子類上的實例很可能是你想要的,因爲每個ThinChild和ThickChild在這種情況下有兩個「myFoo」實例,一個屬於它,另一個屬於父級。

相關問題