覆盖在接口中声明的方法实现

Mik*_*ogh 16 c# inheritance interface

我有一个接口,里面有几种方法.

interface IMyInterface
{
    //...
    void OnItemClicked()
    //...
}
Run Code Online (Sandbox Code Playgroud)

并实施

class MyClass : IMyInterface
{
    //Other methods
    public void OnItemClicked(){ /*...*/ } 
}
Run Code Online (Sandbox Code Playgroud)

现在,我想有一个行为像一个类MyClass除外OnItemClicked(),我要为这个方法进行一些修改.

我想继承一个覆盖,但我不想改变MyClass(如:public virtualvoid OnItemClicked()...),因为它不是我的实现,

我不想IMyInterface再次实现,因为OnItemClicked()是要修改的MyClass的唯一部分.

我还有其他办法吗?

Fra*_*lli 17

由于您正在实现接口,因此您可能希望保留多态性.如果不用虚拟的方法来修改基类,就不可能重写方法,所以你必须使用new而不是像Tigran写的那样使用虚拟.

这意味着编写这种代码但只执行方法的基本版本:

List<MyClass> aList = new List<MyClass>();
aList.Add(new MyClass());
aList.Add(new MyNewClass());
foreach (MyClass anItem in aList)
    anItem.OnItemClicked();
Run Code Online (Sandbox Code Playgroud)

要执行正确的代码,您应该编写丑陋的代码,如下所示:

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();
}
Run Code Online (Sandbox Code Playgroud)

无论如何,当将类分配给声明为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(); 
    } 
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式:

 MyClass cl = new MyNewClass(); 
 cl.OnItemClicked();
Run Code Online (Sandbox Code Playgroud)

执行基本方法

 MyNewClass cl = new MyNewClass(); 
 cl.OnItemClicked();
Run Code Online (Sandbox Code Playgroud)

执行派生类的方法

 IMyInterface cl = new MyNewClass(); 
 cl.OnItemClicked();
Run Code Online (Sandbox Code Playgroud)

执行派生类的方法并在运行时绑定.这意味着您可以像这样编写我的初始示例的代码并执行正确的方法:

List<IMyInterface> aList = new List<IMyInterface>();
aList.Add(new MyClass());
aList.Add(new MyNewClass());
foreach (IMyInterface anItem in aList)
    anItem.OnItemClicked();
Run Code Online (Sandbox Code Playgroud)


Tig*_*ran 5

你可以从中衍生出来 MyClass

public class MyNewClass : MyClass
{
    public new void OnItemClicked(){ /*...*/ } //NEW keyword
}
Run Code Online (Sandbox Code Playgroud)

唯一的事情,注意这种方式你不支持多态.

更清楚:

     MyClass cl = new MyNewClass(); 
     cl. MyMethod();
Run Code Online (Sandbox Code Playgroud)

这将调用MyClass方法,即使真实对象类型是MyNewType.为了能够调用我们想要的东西,我们必须明确地定义类型

     MyNewClass cl = new MyNewClass(); 
     cl. MyMethod(); //WILL CALL METHOD WE WANT
Run Code Online (Sandbox Code Playgroud)