2013-10-24 52 views
2

假設我有一個名爲Fish的超類和一個名爲Tuna的子類。我不明白爲什麼這個工程:困惑於遍歷具有多態性的類層次結構

Fish f; 
Tuna t = new Tuna(); 

f=t; // I am confused about this statement 
f.swim(); // (Tuna's swim method is invoked) 

爲什麼魚變量允許「參與有」(美好短語想要的)更專業的金槍魚對象?我明顯錯誤的「noob OOP Java大腦」的工作方式是:

金槍魚「是一個」魚是好的。魚「是」金槍魚不行。因此f = t不應該是正確的,並且t = f應該是正確的。但從我上面的例子來看,情況正好相反!

非常感謝您的幫助。由於我剛剛開始學習Java,因此我提前爲我的無知道歉。

編輯。以下所有答覆非常感謝。從他們那裏,我現在明白了:

稱爲f的變量是Fish類型,因此可以包含位於變量t中的數據值(對象引用),因爲t指的是Tuna對象,因此是f使用的兼容類型。它是兼容的,因爲金槍魚是魚。

回答

1

f變量的值是一個參考。這可以是空引用,也可以是對「是魚」的任何對象的引用。作爲Tuna對象是Fish對象,可以複製t的值,該值必須是空引用或對對象Tuna的引用。

作業只是將右側的表達式的值複製到左側的變量中。就是這樣。

換句話說:任何你可以對Fish做的事情,你可以做到Tuna。所以沒有價值t這樣的:

f = t; 
f.swim(); 

是荒謬的。 (t可能是理所當然的空引用,但是這並不視爲類型系統爲這樣的問題。)將有始終是一個合適的swim方法來調用,只要t是非空。

將其與另一種類型進行比較。如果我們有:

String s = "foo"; 
f = s; 
f.swim(); 

然後是沒有意義的,因爲你不能要求一個String游泳。

類型安全規則確保您永遠不會嘗試調用方法(或訪問字段),並發現您使用的方法/字段根本不存在。 Tuna延伸Fish的事實意味着任何你可以用「普通」魚做的事情,你也可以用金槍魚做。

+1

字符串不能游泳嗎?我的天啊!我開悟了! –

+0

謝謝!我編輯了我的O.P.以反映我所學到的內容。 – user2911290

2

您近了,但您在一個聲明中錯了。

金槍魚 「是」 魚是OK

我同意 - 這意味着聲明F = T(魚=金槍魚)是正確的。

魚 「是一個」 金槍魚也不行

我同意 - 這意味着聲明T = F(鮪魚=)是不正確的。

。因此,f = t不應該好,並且t = f應該是OK

我不同意,由於上面的狀態表示你剛纔說的相反。 在最後一句中,你說每條魚都是金槍魚(t = f),而不是每條金槍魚都是魚(f = t) - 這顯然是錯誤的。

如果金槍魚是魚,比F = T因爲任何金槍魚都是魚。但是我們不能說每一條魚都是金槍魚嗎?

您必須記住=並不意味着相等(在==中有這樣的做法),爲了更好地理解,請嘗試從右向左讀取這些語句。

+1

+1表示從右向左閱讀。 –

+1

謝謝,我同意,從右向左閱讀「作業複製行動」有助於澄清情況。 – user2911290

1

你有魚超級有游泳的方法,金槍魚是魚的子類。 所以 金槍魚是一種魚:它的好 但魚是金槍魚:不好。 相同 您可以將金槍魚參考分配給魚參考,但魚參考不能金槍魚。 所以

public class Fish { 
    public void swim(){ 
     System.out.print("Hello Fish"); 
    } 
} 

public class Tuna extends Fish{ 
    public void swim(){ 
     System.out.print("Hello Tuna"); 
    } 


    public static void main(String[] ar){ 
     //Case A 
     Fish f=new Fish(); 
     Tuna t; 
     t=(Tuna) f;//wrong - it will not cast to tuna object 
     t.swim(); 
     //Case B //correct 
     Fish f; 
     Tuna t=new Tuna(); 
     t=f 
     t.swim(); 

    } 
} 
+0

不幸的是,「案例B,正確」的代碼不起作用。 – user2911290