2012-09-07 95 views
13

我有一個接口,其中包含多個方法。接口中聲明的覆蓋方法實現

interface IMyInterface 
{ 
    //... 
    void OnItemClicked() 
    //... 
} 

和實施

class MyClass : IMyInterface 
{ 
    //Other methods 
    public void OnItemClicked(){ /*...*/ } 
} 

現在,我想有一個行爲像MyClass除外OnItemClicked()一類,我想這個方法進行一些修改。

我想繼承的覆蓋,但我不想改變MyClass(如:公共virtual無效OnItemClicked()...),因爲它不是我的實現,

我不想再次實現IMyInterface,因爲OnItemClicked()是MyClass的唯一修改部分。

我還有其他辦法嗎?

+0

創建這兩個之間的中間階級。 –

回答

15

由於您正在實現一個接口,多態可能是您想要保留的東西。如果不用虛擬基礎類來調用方法是不可能的,所以你必須使用新的而不是虛擬的,就像Tigran寫的那樣。

這意味着,寫這種代碼,但只有方法的基礎版本將被執行:

List<MyClass> aList = new List<MyClass>(); 
aList.Add(new MyClass()); 
aList.Add(new MyNewClass()); 
foreach (MyClass anItem in aList) 
    anItem.OnItemClicked(); 

要執行正確的代碼,你應該寫醜陋的代碼是這樣的:

List<MyClass> aList = new List<MyClass>(); 
aList.Add(new MyClass()); 
aList.Add(new MyNewClass()); 
foreach (MyClass anItem in aList) 
{ 
    MyNewClass castItem = anItem as MyNewClass; 
    if (castItem != null) 
     castItem.OnItemClicked(); 
    else 
     anItem.OnItemClicked(); 
} 

無論如何,有一種方法可以讓您的類在分配給聲明爲IMyInterface的變量時執行正確的方法。要走的路是明確地實現你想重寫的接口部分,在你的情況下是OnItemClicked方法。該代碼是下面的:

public class MyNewClass : MyClass, IMyInterface // you MUST explicitly say that your class implements the interface, even if it's derived from MyClass 
{ 
    public new void OnItemClicked() //NEW keyword here you have the overridden stuff 
    { 
     /*...*/ 
    } 

    void IMyInterface.OnItemClicked() // No need for public here (all interfaces's methods must be public) 
    { 
     this.OnItemClicked(); 
    } 
} 

以這種方式:

MyClass cl = new MyNewClass(); 
cl.OnItemClicked(); 

執行基方法

MyNewClass cl = new MyNewClass(); 
cl.OnItemClicked(); 

執行派生類的方法

IMyInterface cl = new MyNewClass(); 
cl.OnItemClicked(); 

執行派生的方法ved類並在運行時綁定。這意味着,你可以寫我喜歡這個最初的例子的代碼,並且執行正確的方法:

List<IMyInterface> aList = new List<IMyInterface>(); 
aList.Add(new MyClass()); 
aList.Add(new MyNewClass()); 
foreach (IMyInterface anItem in aList) 
    anItem.OnItemClicked(); 
5

可以派生從MyClass

public class MyNewClass : MyClass 
{ 
    public new void OnItemClicked(){ /*...*/ } //NEW keyword 
} 

的唯一的事情,要注意,在這種方式,你不必supprot多態性。

更清楚:

 MyClass cl = new MyNewClass(); 
    cl. MyMethod(); 

這將調用MyClass方法,即使真正對象類型爲MyNewType。 爲了能夠調用我們想要的,我們必須esplicitly定義類型

 MyNewClass cl = new MyNewClass(); 
    cl. MyMethod(); //WILL CALL METHOD WE WANT 
+0

他在他的文章中提到:我想繼承一個覆蓋,但我不想更改MyClass(如:public virtual void OnItemClicked()...),因爲它不是我的實現, –

+0

@ armen.shimoon:沒有。你在哪裏看到改變MyClass實現的代碼? – Tigran

+0

我的壞Tigran。我瀏覽了代碼,並認爲你已經「覆蓋」而不是「新」。問題:當MyNewClass被用作「IMyInterface」的實例時,將調用哪個方法? –

3

最簡單的方法是創建一個新的類,它模仿「是一個」用「有-a「:

public interface IMyInterface 
{ 
    void OnItemClicked(); 
    void OnItemHover(); 
    void OnItemDoubleClicked(); 
} 

public class MyNewClass : IMyInterface 
{ 
    private IMyInterface _target; 

    public MyNewClass(IMyInterface target) 
    { 
     _target = target; 
    } 

    public void OnItemClicked() 
    { 
     // custom functionality 
    } 

    public void OnItemHover() 
    { 
     _target.OnItemHover(); 
    } 

    public void OnItemDoubleClicked() 
    { 
     _target.OnItemDoubleClicked(); 
    } 
} 
+0

好的,但你不能將此分配給一個MyClass變量 –

+0

是的,但在答案中,你可以將它分配給一個MyClass變量,你調用OnItemClicked()它會執行錯誤功能。我假設界面是重要的部分,否則這將無法正常工作,但其他答案也不會。 –

+0

你說得對,其實我更喜歡你的答案,我只是指出爲什麼我更喜歡我的答案給你:-) –