2012-09-07 56 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

你说得对,其实我更喜欢你的答案,我只是指出为什么我更喜欢我的答案给你:-) –