2011-10-12 69 views
0

這可能是回答某處,但我不知道要搜索什麼。想象一下,你有以下...實例變量調用在你做什麼時工作A thing = new B();其中B是A的一個子類?

超類,Animal.java

public class Animal { 
    public String noise = "squeak"; 
    public String toString() { return noise; } 
} 

子類,Lion.java

public class Lion extends Animal { 
    public String noise = "ROAR!!"; 
    public String toString() { return noise; } 
} 

的主類,Runner.java

public class Runner { 
    public static void main(String[] args) { 
    Animal a = new Animal(); 
    System.out.println(a); 
    System.out.println(a.noise); 
    Lion b = new Lion(); 
    System.out.println(b); 
    System.out.println(b.noise); 
    Animal c = new Lion(); 
    System.out.println(c); 
    System.out.println(c.noise); 
    } 
} 

輸出結果爲:

squeak 
squeak 
ROAR!! 
ROAR!! 
ROAR!! 
squeak 

c.noise爲什麼會返回吱吱聲?實例方法調用和實例變量之間的區別是什麼,它會返回您期望的結果,而另一個則不會?爲什麼Java會這樣做?

感謝

+1

我不是Java專業人員,所以我不會稱這爲答案,但區別在於Java中的方法是虛擬的。也就是說,當你調用c.toString()時,Java通過使用查找表知道使用正確的方法是Lion的toString()。但是,這種虛擬化不會發生在實例變量上。 – erisco

回答

3

簡短的回答:

您可以替代的方法,但它不可能覆蓋領域。

龍答:

每個班級看到的方法和它自己和它的父母的領域(除私有方法)。如果孩子在名稱相同的情況下刪除方法在其父類中的名稱,則此方法將變爲覆蓋 - 如果以某種方式在子實例上調用此方法(即使是從父方法),將使用全新的方法而不是父級的方法。孩子仍然可以通過電話super.method(...)致電最後一位家長的原始方法。

但是當我們來到田野時,故事是不同的。如果孩子聲明瞭一個新的字段,該字段的名稱與父類中的字段完全一樣,它將簡單地隱藏父類的字段不重寫,就像本地變量隱藏全局字段一樣。所以子方法只會看到孩子的字段,但父母的方法會繼續看到父母的字段,並且父類的任何方式都無法看到孩子的字段 - 這就是你所得到的。

孩子可以通過((Parent)this).field訪問其父母的字段。

+0

當他們說「類方法/字段」時,大多數人的意思是靜態方法/字段,但我很確定你是指實例方法/字段。 –

+0

對不起,爲了避免含糊不清,更正。 –

2

較長的答案:

所以真的你會做到這一點的方法是這樣定義的獅子:所以現在

public class Lion extends Animal { 
    public Lion() { 
    noise = "ROAR!!"; 
    } 
} 

的獅子實例動物的噪音成員變量已經更新到吼!

當然,你(幾乎)從來沒有在類似野外的類上實際擁有一個公共可變成員。

2

您無法覆蓋字段,中的noise的新聲明會隱藏父項的noise屬性。像這樣:

public class Lion extends Animal { 

// public String noise = "ROAR!!"; // <---- Remove this line 

    public Lion() { 
     noise = "ROAR"; 
    } 

    public String toString() { 
     return noise; 
    } 
} 
1

java中的所有非靜態方法默認爲"virtual functions"。除非它們被標記爲final(這使得方法不可覆蓋)。 Java使用virtual method table來調用正確的對象的方法。

1

這是因爲Java只談約方法覆蓋。成員變量只能在子類中映射。所以當你說c.noise時,它實際上是指父類中的字符串變量作爲c,如果引用類型爲Animal。

0

您感興趣的主題有Dynamic DispatchVirtual Method Table。基本上,通過設計,Java允許重寫方法(假設它們是非最終的),並且在運行時JVM將執行相應的實現。這個多態屬性只提供給方法。好的OO設計將決定封裝這些字段。

相關問題