在層次結構中,在某個點使用new
關鍵字來覆蓋方法中的返回類型是否正常?C#中的新操作符和虛擬操作符
我可以使用virtual new
或new virtual
,這樣我可以重寫返回類型嗎?
我還需要考慮從那個點繼承的類。他們可以重寫這種方法,其基地是用new
創建的?
在層次結構中,在某個點使用new
關鍵字來覆蓋方法中的返回類型是否正常?C#中的新操作符和虛擬操作符
我可以使用virtual new
或new virtual
,這樣我可以重寫返回類型嗎?
我還需要考慮從那個點繼承的類。他們可以重寫這種方法,其基地是用new
創建的?
你可以這樣做,但真正的問題是你是否應該做到這一點。
問題是,你會得到非常意想不到的行爲,這取決於你的類如何使用。如果你從基類的一個實例中調用你的類,原始的非「新」方法將被調用,這可能是意想不到的。
一般來說,我會避免使用new關鍵字來覆蓋基類方法,除非有非常明確的理由這樣做 - 如果您的方法將返回一個新類型,請將其聲明爲一個新方法一個不同的名稱或簽名,而不是隱藏基類方法 - 它會使您的層次更加可用。
打趣....
public class BaseCollection<T>
{
// void return - doesn't seem to care about notifying the
// client where the item was added; it has an IndexOf method
// the caller can use if wants that information
public virtual void Add(T item)
{
// adds the item somewhere, doesn't say where
}
public int IndexOf(T item)
{
// tells where the item is
}
}
public class List<T> : BaseCollection<T>
{
// here we have an Int32 return because our List is friendly
// and will tell the caller where the item was added
new public virtual int Add(T item) // <-- clearly not an override
{
base.Add(item);
return base.IndexOf(item);
}
}
這裏我使用了「新」的修改,因爲列表<牛逼>參考將從BaseCollection <牛逼>隱藏Add方法。默認情況下,隱藏基本成員會從編譯器生成警告(如果編譯設置爲警告失敗,則爲錯誤)。所以我基本上是在告訴編譯器......「是的,我知道我使用void return隱藏了Add方法,它是所需的功能 - 只需要使用它。」
我完全同意。你應該有一個非常有說服力的理由這樣做。繼承關係是「IS A」關係,所以如果A從B繼承,那麼A就是B.這意味着A也應該表現得好像它是B. – Pete 2009-09-24 17:21:36
我完全同意你的看法。我這樣做的原因是因爲我正在使用遺留代碼:(它是這樣做的,我可以改變它,我也不喜歡它,但我也是,我現在唯一確定的是它將使用所有將使用新類的地方,至少從聲明「新」類的地方調用 – jmayor 2009-09-24 17:43:08
正如我所說,你可以這樣做 - 我個人會建議切換方法名,特別是儘管如此,避免這種情況,它使生活非常混亂。 – 2009-09-24 17:53:36