什麼是在鹼型「virtual
」聲明的方法,然後使用「override
」關鍵字覆蓋它在一個子類型,而不是之間的差異,以簡單地使用「new
」關鍵字時聲明子類型中的匹配方法?C# - 關鍵字的使用虛擬+倍率與新
回答
「new」關鍵字未覆蓋,表示與基類方法無關的新方法。
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
public class Test
{
public static void Main()
{
Foo test = new Bar();
Console.WriteLine (test.DoSomething());
}
}
這將打印假的,如果你使用的覆蓋,將印有真實的。
(從約瑟夫·代格爾採取的基本代碼)
所以,如果你是做真正的多態性你應該總是覆蓋。唯一需要使用「新」的地方是該方法與基類版本沒有任何關係。
你應該修改你的代碼,我已經使靜態方法(這是對於使用「新」關鍵字有效)。但我決定使用實例方法更清晰。 – 2008-10-01 22:16:41
謝謝,我錯過了「靜態」部分。應該注意未來 – albertein 2008-10-01 22:17:57
請注意,Foo test = new Bar()這一行至關重要,metods的新/ override關鍵字決定了將Bar放入Foo變量時調用哪個metod。 – 2015-04-20 13:00:38
new
關鍵字實際上會創建一個僅存在於該特定類型上的全新成員。
例如
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
的方法,存在於這兩種類型。當您使用反射並獲得Bar
類型的成員時,實際上會發現兩種方法,名稱爲DoSomething()
,看起來完全相同。通過使用new
,您可以有效地隱藏基類中的實現,以便在類別從Bar
(在我的示例中)派生到base.DoSomething()
的方法調用轉到Bar
而不是Foo
。
下面是一些代碼來了解在虛擬和非虛擬方法的行爲差異:
class A
{
public void foo()
{
Console.WriteLine("A::foo()");
}
public virtual void bar()
{
Console.WriteLine("A::bar()");
}
}
class B : A
{
public new void foo()
{
Console.WriteLine("B::foo()");
}
public override void bar()
{
Console.WriteLine("B::bar()");
}
}
class Program
{
static int Main(string[] args)
{
B b = new B();
A a = b;
a.foo(); // Prints A::foo
b.foo(); // Prints B::foo
a.bar(); // Prints B::bar
b.bar(); // Prints B::bar
return 0;
}
}
除了技術細節之外,我認爲使用虛擬/覆蓋可以在設計上傳達大量的語義信息。當你聲明一個虛擬的方法時,你表明你期望實現類可能想要提供他們自己的非默認實現。同樣,在基類中省略這一點同樣聲明瞭對於所有實現類都應該滿足缺省方法的期望。同樣,可以使用抽象聲明來強制實現類提供自己的實現。再次,我認爲這會傳達很多關於程序員期望如何使用代碼的信息。如果我正在編寫基礎和實現類,並發現自己使用新的,我會認真重新考慮不要在父項中使方法虛擬並明確聲明我的意圖的決定。
虛擬/清除告訴,這兩種方法都涉及編譯器,而且在某些情況下,您會認爲你所呼叫的第一(虛擬)方法實際上它是正確的調用第二個(覆蓋)方法來代替。這是多態性的基礎。
(new SubClass() as BaseClass).VirtualFoo()
將調用子類的重寫VirtualFoo()方法。
new告訴編譯器,您正在向派生類中添加一個方法,它與基類中的方法具有相同的名稱,但它們彼此沒有關係。
(new SubClass() as BaseClass).NewBar()
將調用BaseClass的的NewBar()方法,而:
(new SubClass()).NewBar()
將調用子類的NewBar()方法。
我總是覺得這樣的事情有圖片更容易理解:
再次重申,在約瑟夫·代格爾的代碼,
public class Foo
{
public /*virtual*/ bool DoSomething() { return false; }
}
public class Bar : Foo
{
public /*override or new*/ bool DoSomething() { return true; }
}
如果你再這樣調用代碼:
Foo a = new Bar();
a.DoSomething();
注意:重要的是我們的對象實際上是一個Bar
,但我們是將它存儲在變量o F型Foo
(這類似於澆鑄)
那麼結果將是如下,這取決於你聲明你的類時使用virtual
/override
或new
。
new
關鍵字是隱藏。 - 意味着你在運行時隱藏了你的方法。輸出將基於基類方法。override
重寫。 - 意味着您正在調用派生類方法並引用基類。輸出將基於派生類方法。
我的解釋版本來自於使用屬性來幫助理解差異。
override
很簡單吧?基礎類型覆蓋父母的。
new
也許是誤導(對我而言)。隨着性能更容易理解:
public class Foo
{
public bool GetSomething => false;
}
public class Bar : Foo
{
public new bool GetSomething => true;
}
public static void Main(string[] args)
{
Foo foo = new Bar();
Console.WriteLine(foo.GetSomething);
Bar bar = new Bar();
Console.WriteLine(bar.GetSomething);
}
使用調試器,你可以看到,Foo foo
有2個GetSomething
屬性,它實際上有兩個版本的屬性,Foo
的和Bar
的,要知道哪一個使用,c#「挑選」當前類型的屬性。
如果您想使用Bar的版本,您可能會使用覆蓋或使用Foo foo
代替。
Bar bar
只有,因爲它完全新行爲要進行GetSomething
。
- 1. 在C++中使用虛擬關鍵字
- 2. 虛擬關鍵字
- 3. 偏差與虛擬關鍵字
- 4. c中的虛擬關鍵字#
- 5. C#虛擬&覆蓋關鍵字
- 6. 尋找成員函數倍率(非虛擬的)的C++溶液
- 7. 虛擬關鍵字與類聲明的用法
- 8. 我們可以在c#的方法中同時使用虛擬關鍵字和新關鍵字嗎?
- 9. 缺少虛擬關鍵字的警告
- 10. 如何避免虛擬關鍵字
- 11. 虛擬關鍵字內部組件
- 12. 新關鍵字的真實用法隱藏虛擬方法實現? c#
- 13. 虛擬關鍵字和庫提前
- 14. 啓用/禁用Android的虛擬鍵盤與虛擬的textarea
- 15. 不使用虛擬關鍵字的多態性
- 16. C中的虛擬鍵盤#
- 17. 「虛擬」是C++中的限定符還是關鍵字?
- 18. 使用C#中的新關鍵字
- 19. 虛擬關鍵字與g ++(Ubuntu)的奇怪(?)行爲
- 20. 爲什麼所有關於虛擬關鍵字的模糊?
- 21. C++虛擬關鍵字vs覆蓋函數
- 22. C++:使虛擬
- 23. 使用新的關鍵字
- 24. 虛擬和新的C#
- 25. 虛擬PC高CPU使用率問題
- 26. 虛擬內存使用率高
- 27. Node.js虛擬內存使用率高
- 28. 使用「新」關鍵字
- 29. C++關鍵字使用
- 30. const關鍵字使用C++
[MSDN](http://msdn.microsoft.com/en-us/library/435f1dw2%28v=vs.80%29.aspx)說:「使用`new`會創建一個具有相同名稱的新成員,導致原始成員隱藏,而「覆蓋」擴展了繼承成員的實現「 – AminM 2013-08-14 12:04:31
請參閱http://stackoverflow.com/questions/17717570/why-does-calling-a-method-in-my-derived -class-call-the-base-class-method – 2013-08-20 11:43:44
MSDN - http://msdn.microsoft.com/en-us/library/ms173153.aspx – dayuloli 2014-04-14 10:31:21