2014-09-13 30 views
0

在下面的例子中,我不明白爲什麼Base b1 = new Derived(); System.out.println(b1);打印出x=10, z=20。我的理解是,因爲b1有一個靜態類型的基地,它不能訪問Derived中的字段,所以z不應該打印出來。有人可以幫忙解釋嗎?非常感謝!Java更寬的對象分配轉換

class Base { 
    int x; 
    public Base1() { x = 10; } 
    public Base1(int x) { this.x =x; } 
    public String toString() { 
    return "x=" + x ; 
    } 
} 
class Derived1 extends Base1 { 
    int z = x * 2; 
    public Derived1() {} 
    public Derived1(int x, int z) { 
     super(x); 
     this.z = this.z + z; 
    } 
    public String toString() { 
     return "x=" + x + ", z=" + z; 
    } 
    } 
+1

這是多態性的全部目的。 – 2014-09-13 09:20:08

+0

https://en.wikipedia.org/wiki/Method_overriding – khelwood 2014-09-13 09:34:27

回答

2

對象Derived,而不是一個Base。您的接口b1的對象是BaseBasetoString,所以你可以訪問toString。您訪問的實現是對象所具有的實現,它由Derived提供,它使用zDerived#toString的實現可以訪問z,因爲其對對象的引用是通過Derived引用(this)引用的,而不是Base引用。

正如Oli在評論中指出的那樣,這對多態性具有根本性  —使對象的行爲取決於對象而不是對象的接口。

如果對象的內部是由我們所需的接口決定的,那麼嘗試執行interface s就會遇到一些麻煩! :-)

+0

謝謝!我仍然有點困惑,因爲我記得老師說過這樣的話:「這個更廣泛的任務是可以的,但是b1不能訪問Derived中的字段。」那麼這是指什麼?這是否意味着它可以通過方法訪問z,就像你說的,但它不能通過b1.z訪問? – user3735871 2014-09-13 09:33:51

+1

@ user3735871:這意味着使用'b1'的代碼只能訪問'Base'定義的東西,即使對象是一個Derived。這些可能是新方法或新領域。就代碼*使用*'b1'而言,'b1'是一個'Base'。但是,當使用'b1'的代碼調用由'Base'定義但由Derived實現的對象的方法時,該方法中的代碼可以訪問Derived定義的所有內容。所以是的,'b1.z'不可訪問,但'b1.toString'可以訪問'z',因爲'b1.toString'由'Derived'實現。 – 2014-09-13 09:38:31

+0

謝謝。現在它變得更有意義!還有一個問題:如果Base中沒有toString方法,或者Base中沒有toString方法,那麼Derived類將無法覆蓋它來訪問z? – user3735871 2014-09-13 09:50:04

1

直接從http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

子類繼承其所有 母公司的公共和保護的成員,無論子類是在什麼包,如果子類在同一個包 它的父項,它也繼承父項的包私有成員 。您可以使用繼承 成員是,取代他們,隱藏起來,或者用新 成員

在你的代碼調用默認的構造函數來創建一個新的Derived1對象加以補充:
Base b1 = new Derived();,這反過來又調用父類的默認構造函數,在那裏你碰巧設置了x = 10。之後,你去這條線int z = x * 2;