2010-05-19 78 views
1

假設我有一個SuperClass類和兩個繼承自SuperClass的子類SubClassA和SubClassB。「覆蓋」子類型中的實例變量:可能的風險?

abstract class SuperClass{ 
    ... 
    List someList; 
    ... 
} 

class SubClassA extends SuperClass{ 
    ... 
    List<String> someList; 
    ... 
} 

class SubClassB extends SuperClass{ 
    ... 
    List<Integer> someList; 
    ... 
} 

這樣很方便,因爲我可以在Superclass得到someList.size()並在子類具有類型安全。 問題是它沒有「感覺」正確,你能想到這個應用程序的潛在危害,我不知道嗎?

回答

8

首先,SuperClass的任何方法都會看到超類列表,而不是子類。這幾乎肯定會導致微妙的錯誤。例如。當你說

我可以在Superclass

你真正得到的是列表中Superclass的大小,而不是子類的拿到someList.size()。超類列表可能爲空而子類列表包含元素(反之亦然)。

這背後的原因是,SubClassA.someList不以任何方式替代或覆蓋Superclass.someList - 它只是陰影,所以子類方法見SubClassA.someList,而不是Superclass.someList。但是,這在Superclass中絕對沒有影響。方法可以是虛擬的(在Java中,它們是默認的),但數據成員不能。

+0

它們可能是指向同一對象的不同引用。 (儘管'private'和'final'將會像以前一樣有幫助。) – 2010-05-19 11:34:55

+0

@Tom,好點,沒有想到...可能是因爲,雖然語義上正確,但這仍然是一個醜陋的,不必要的複雜的,很難了解解決方案(對我)。 – 2010-05-19 12:02:54

+0

我發現了困難的方式,它實際上是陰影。我在這裏做的唯一事情就是編譯器(和我)的伎倆。 – sebastiangeiger 2010-05-20 18:52:58

1

這是一個非常糟糕的主意。你真的想要任一個子類的實例有兩個列表嗎?因爲這就是發生的事情。你聲明瞭第二個變量 - 因此超類中的代碼將使用一個變量,並且子類中的代碼將使用另一個變量。這只是要求麻煩,海事組織。

1

似乎打破IS-A和Liskov替代原則給我。如果你有一個SuperClass實例集合,其中的每一個都可以是SubClassA或SubClassB,你最多可以得到一些令人驚訝的行爲。

不要這樣做。

也許使用泛型的東西會更好:

public class X<T> 
{ 
    private List<T> list; 
} 
1

我想你應該比較定義方法,而不是類的成員變量。這樣你就可以在你的子類中實現方法,並且不需要擔心類型的安全性。

用我建議的方法替換變量。

謝謝。