2013-01-25 190 views
50

假設如果我有一個接口,定義如下:C#接口繼承到抽象類

public interface IFunctionality 
{ 
    void Method();  
} 

和我實現該接口用於一個抽象類,如下所示:

public abstract class AbstractFunctionality: IFunctionality 
{ 
    public void Method() 
    { 
     Console.WriteLine("Abstract stuff" + "\n"); 
    }  
} 
再次

我有一個具體類繼承抽象類如下:

public class ConcreteFunctionality: AbstractFunctionality 
{ 
    public void Method() 
    { 
     Console.WriteLine("Concrete stuff" + "\n"); 
    } 
} 

現在我有以下的co de,

ConcreteFunctionality mostDerived = new ConcreteFunctionality(); 
AbstractFunctionality baseInst = mostDerived; 
IFunctionality interfaceInst = mostDerived; 
mostDerived.Method(); 
baseInst.Method(); 
interfaceInst.Method(); 

執行這個東西后我得到的輸出如下。

Concrete stuff 
Abstract stuff 
Abstract stuff 

但我一直期待的輸出爲「具體的東西」在所有的三種情況是什麼,我這裏做的是分配的ConcreteFunctionalityAbstractFunctionality類型和IFunctionality的變量的引用。

內部發生了什麼。請澄清。

+2

這可能會清除一些東西:http://stackoverflow.com/questions/392721/difference-between-shadowing-and-overriding-in-c – Stormenet

+0

「這是隱藏的,沒有被覆蓋」 - 一個很好的口號要記住。 (但是你的編譯器應該提到這個;你是否已經過濾了你的警告?) – kmote

回答

74

這裏:

public class ConreteFunctionality:AbstractFunctionality 
{ 
    public void Method() 
    { 
     Console.WriteLine("Concrete stuff" + "\n"); 
    } 
} 

...你不重寫現有方法。您正在創建一個新的方法,其中隱藏現有的一個。 (你也應該得到一個警告,如果你真的想要這種行爲,建議使用new修飾符)。接口在AbstractFunctionality中實現,因此接口映射表引用該類中的方法。

現在,如果你重新實現接口:

public class ConcreteFunctionality : AbstractFunctionality, IFunctionality 

...那麼接口映射將參考方法ConcreteFunctionality,你會得到你所期望的通過接口調用行爲(即你的第三個電話),但你仍然可以在AbstractFunctionality中執行你的第二個電話。

這將是一般更清潔和更健全的保留,使AbstractFunctionality虛擬方法,並覆蓋它在ConcreteFunctionality。這樣它將在所有情況下使用ConcreteFunctionality實現。

+1

這不會給預期的行爲,因爲第二次調用仍然是通過抽象實現。 –

+0

@JonHanna:我沒有注意到第二次調用會使用具體版本的期望。將編輯。 –

14

您錯過了virtualoverride關鍵字。沒有這個你不會得到虛函數。

可以標誌着AbstractFunctionality Method作爲virtual並標記ConreteFunctionalityMethodoverride。正如mihirj所示。

在解決類似的問題 - Why are C# interface methods not declared abstract or virtual?

+1

對於有趣的鏈接+1。 – phoog

30

您需要定義類爲:

public abstract class AbstractFunctionality:IFunctionality 
{ 
    public virtual void Method() 
    { 
     Console.WriteLine("Abstract stuff" + "\n"); 
    }  
} 

public class ConreteFunctionality:AbstractFunctionality 
{ 
    public override void Method() 
    { 
     Console.WriteLine("Concrete stuff" + "\n"); 
    } 
} 

由於您沒有在ConreteFunctionality覆蓋方法(),在運行時環境中執行方法()與AbstractFunctionality相關因爲它不能在這裏應用動態多態。引入virtualoverride使運行時環境在子類中執行重寫方法。

+2

不錯的答案;但我會介紹術語「隱藏」,它描述了OP的原始代碼,並注意隱藏一個沒有「new」關鍵字的方法會導致編譯器警告。 – phoog