2015-12-28 35 views
2

我有一個多態性和顯式強制轉換的小問題。 這是問題所在: 我有3個公共課:顯式強制操作符和多態性

package x; 

public class Shape 
{ 
public void draw(){ 
    System.out.println("draw a Shape"); 
} 
} 

package x; 

public class Circle1 extends Shape 
{ 

} 

package x; 

public class Circle2 extends Circle1 
{ 
    @Override 
    public void draw() 
    { 
     System.out.println("draw Circle2"); 
    } 
} 

我的Demo類是:

package x; 

public class Demo 
{ 
    public static void main (String[] args) 
    { 

     Shape s1=new Circle2(); 
     s1.draw(); 
     ((Shape)s1).draw(); 

    } 
} 

這段代碼的輸出是:

平局CIRCLE2
繪製Circle2

我瞭解s1.draw()的多態行爲,它調用Circle2上的draw()方法。 最後一行讓我感到困惑,當我在s1上進行顯式強制轉換時,如下所示:((Shape)s1),這表示((Shape)s1)是表達式類型的引用,因爲顯式強制轉換,對吧? 如果是這樣,那麼爲什麼然後代碼((Shape)s1).draw();調用Circle2中的draw()方法,而不是Shape中的方法?

謝謝:)

+0

's1'已經有'形狀'類型...所以演員陣容沒有任何意義 –

回答

3

鑄造不會改變對象,它只是改變了編譯器應該如何該對象看看

所以,即使你認爲一個圓是「只是一個形狀」,它仍然保持一個圓。

Circle1調用Shape的平局就從Circle1通過調用super.draw()

0

當你明確(或隱含的)對象轉換一個超類型的方法將總是唯一的辦法服從用於構建對象的類的實現。在你的情況下,因爲你的物體是用new Circle2()構造的,即使你投了它,它也將永遠是一個Circle2。事實上,你有一個簡單的方法來看到這一點。只需以下行添加到您的代碼:

Shape s2 = (Shape) s1; 
System.out.println(s2.getClass().getName()); 

這將打印您s2對象(從S1鑄造)屬於:)你會看到它仍然是一個CIRCLE2的確切類。

如果您想要調用draw()方法的超類型實現,則需要改爲撥打super.draw()