2008-12-25 56 views

回答

128

好繼承...

假設你有這樣的類:

class A { 
    public int Foo(){ return 5;} 
    public virtual int Bar(){return 5;} 
} 
class B : A{ 
    public new int Foo() { return 1;}  //shadow 
    public override int Bar() {return 1;} //override 
} 

然後當你調用這個:

A clA = new A(); 
B clB = new B(); 

Console.WriteLine(clA.Foo()); // output 5 
Console.WriteLine(clA.Bar()); // output 5 
Console.WriteLine(clB.Foo()); // output 1 
Console.WriteLine(clB.Bar()); // output 1 

//now let's cast B to an A class 
Console.WriteLine(((A)clB).Foo()); // output 5 <<<-- shadow 
Console.WriteLine(((A)clB).Bar()); // output 1 

假設你有一個基類,並使用基地類,而不是繼承的類,並且使用shadow,它將返回基類返回的值,而不是跟隨對象的實際類型的繼承樹。

Run code here

希望我做的意義:)

+11

重寫提供多態性,影子在層次結構的該級別提供了不同的實現,但不是多態的。 – 2008-12-25 11:10:21

+0

@dribeas,你會用什麼定義多態性來得出結論? – AnthonyWJones 2008-12-25 13:26:50

6

我認爲主要的區別在於,使用陰影時,基本上重用名稱,而忽略超類的使用。重寫時,您將更改實現,但不會改變可訪問性和簽名(例如參數類型和返回值)。見http://www.geekinterview.com/question_details/19331

31

陰影實際上是VB說法什麼,我們就稱之爲隱藏在C#。

通常隱藏(VB中的陰影)和覆蓋顯示爲在Stormenet的回答。

虛擬方法被顯示爲被子類覆蓋,並且即使在超類類型或從超類的內部代碼中調用該方法也會從子類調用替換實現。

然後,在定義子類上具有相同簽名的方法時,通過使用new關鍵字隱藏了一個具體方法(一個未標記爲虛擬或抽象)。在這種情況下,當在超類類型上調用方法時,將使用原始實現,新實現僅在子類上可用。

但是經常會漏掉的是,它也可以隱藏虛擬方法。

class A 
{ 
    public virtual void DoStuff() { // original implementation } 
} 

class B : A 
{ 
    public new void DoStuff() { //new implementation } 
} 

B b = new B(); 
A a = b; 

b.DoStuff(); //calls new implementation 
a.DoStuff(); //calls original implementation. 

請注意,在上面的例子中,DoStuff變得具體而且不能被重寫。不過,也可以將virtualnew兩個關鍵字一起使用。

class A 
{ 
    public virtual void DoStuff() { // original implementation } 
} 

class B : A 
{ 
    public new virtual void DoStuff() { //new implementation } 
} 

class C : B 
{ 
    public override void DoStuff() { //replacement implementation } 
} 

C c = new C(); 
B b = c; 
A a = b; 

c.DoStuff(); //calls replacement implementation 
b.DoStuff(); //calls replacement implementation 
a.DoStuff(); //calls original implementation. 

需要注意的是,儘管所有的方法參與是虛擬的,C上的覆蓋並不影響A上的虛方法,因爲在B中使用的new的隱藏了一個實施過程。

編輯:它已在評論中注意到這個答案,上述可能是危險的,或至少不是特別有用。我會說是的,它可能是危險的,如果它在所有有用的,它會在那裏。

特別是,如果您還更改可訪問性修飾符,則可能會遇到各種麻煩。例如: -

public class Foo 
{ 
    internal Foo() { } 
    protected virtual string Thing() { return "foo"; } 
} 

public class Bar : Foo 
{ 
internal new string Thing() { return "bar"; } 
} 

Bar外部繼承者,Foo的實現的東西()保持入店和重寫。根據.NET類型規則,所有合法和可解釋的東西都是非常不直觀的。

我已經發布了這個答案,以加深對事物如何工作的理解,而不是作爲可以自由使用的技術的建議。

0

基本上,如果您有類似下面,

Class A 
{ 
} 

Class B:A 
{ 
} 

A a = new B(); 

你的對象「A」將在的「A」的類型進行(這裏的類型是「A」)上調用任何方法 但如果您在Class A中已經存在的類B中實現了相同的方法,那麼編譯器會給您一個警告,使用「New」關鍵字。如果您使用「新建」,警告將消失。除此之外,在使用「新建」或不在繼承類中使用它們之間沒有區別。

在某些情況下,您可能需要調用引用類的方法,而不是在對象類型上調用某個方法。在上述情況下,它所保留的參考是'B',但類型是'A'。所以如果你想讓方法調用發生在'B'上,那麼你使用虛擬並重寫來實現這一點。

希望這會有所幫助...

Daniel Sandeep。

3

遮蔽是VB.NET的概念。在C#中,陰影被稱爲隱藏。它隱藏了派生類的方法。它使用'new'關鍵字完成。

覆蓋關鍵字用於在派生類中提供基類方法(標記爲「虛擬」)的全新實現。

相關問題