2009-01-30 106 views
5

我有一個關於在Java中繼承和鑄造的問題。我有以下兩個示例類和一個測試類,我陳述的類後,我的問題:在Java中繼承和鑄造

public class Automobile { 
    public int var; 

    public Automobile() { 
     var = 1; 
    } 

    public String toString() { 
     return "AUTOMOBILE: " + var; 
    } 
} 


public class Porsche extends Automobile { 
    public int var; 

    public Porsche() { 
     var = 2; 
    } 

    public String toString() { 
     return "PORSCHE: " + var; 
    } 
} 

public class Test { 
    public static void main (String [] args) { 
     Porsche p = new Porsche(); 
     Automobile a = new Automobile(); 

     System.out.println ("(Automobile) p = " + (Automobile)p); 

     System.out.println ("(Automobile) p.var = " + ((Automobile)p).var); 
    } 
} 

輸出是:

(Automobile) p = PORSCHE: 2 
(Automobile) p.var = 1 

我不明白,爲什麼在第二個發言中,我們有1。不是2?因爲在我的第一個語句投p來汽車我仍然得到PORSCHE: 2p表示 - 我明白這一點通過以下方式:

不過我已經鑄造p到汽車p保持其「本來面目」 - p是這是保時捷課程的一個對象,但由於保時捷延續了汽車,我們可以說P也是汽車。因此,當我們明確地將其投放到汽車時,它會繼續使用其方法 - 在 我們的情況下,在保時捷中定義的方法toString()

在另一方面,如果我寫的東西是正確的,那麼第二個print語句應該給2,而不是1

現在,這似乎是一個矛盾的我,但因爲這部作品在Java中,似乎我不明白在投射和繼承過程中發生了什麼。

回答

16

我相信你實際上不能用Java重寫變量。該子類實際上'隱藏'變量var

當您轉換爲Automobile時,您將獲得var變量的父類版本。但是,toString()方法仍在查看實例版本的var變量。

如果您從保時捷子類中刪除public int var,它應該按預期工作。

應該指出的是,使用公共實例變量不是好習慣,你應該總是創建getters/setter來擁有合適的encapsulation

5

變量的陰影var

您的Porche.var是一個與Automobile.var不同的變量。

Porsche.toString()方法使用Porsche.var,而演員告訴編譯器使用Automobile版本。

2

對字段的訪問不是多態 - 它僅取決於表達式的編譯時類型。

表達式((Automobile)p)具有編譯時型Automobile,所以使用它的字段。

1

在這兩個類中聲明變量「var」實際上在內存中創建了兩個字段。

「保時捷」的一個實例將在內存中有兩個「var」字段,其中一個是「Porsche」類,另一個是超級類「Automobile」。當您從已知的「Porsche」實例中引用「var」時,超類的「var」字段將被隱藏。如果您將此實例轉換爲「Automobile」並引用「var」字段,則引用「Automobile」的var字段。

沒有壓倒一切的領域。同名的新字段掩蓋了超類的字段。

爲了獲得預期的結果,您不應在「Porsche」類中聲明「var」字段。

0

然而:

如果有,它返回父類A的對象的方法,它可以返回任何對象鍵入延伸它的一類(工廠的實施例)。現在,如果此方法返回一個子類B對象,並且如果不將它強制轉換爲B,則其所有屬性都將是父屬性。如果你將它投射到B,那麼它的屬性將是A和B屬性。

class A { 
int a1,a2; 
public A(){} 


    public static A getInstance() { 
    return new B() ; 
    } 
} 
class B { 
int b1,b2; 
    public B() {} 

} 
class Test{ 

public static void main (String [] args) { 

    A theA = A.getInstance() ; //here theA has only a1,a2 as attributes 
    B theB = (B)theA // here theB has b1,a2 and a1,a2 as attributes 
    } 


}