Jam*_*hon 9 c# oop syntax interface
覆盖子类中接口的显式实现的正确方法是什么?
public interface ITest
{
string Speak();
}
public class ParentTest : ITest
{
string ITest.Speak()
{
return "Meow";
}
}
public class ChildTest : ParentTest
{
// causes compile time errors
override string ITest.Speak()
{
// Note: I'd also like to be able to call the base implementation
return "Mooo" + base.Speak();
}
}
Run Code Online (Sandbox Code Playgroud)
以上是对语法的最佳猜测,但显然这是错误的.它会导致以下编译时错误:
`ChildTest.ITest.Speak()':虚拟或抽象成员不能是私有的
ChildTest.ITest.Speak()': containing type does not implement interfaceITEST"
修饰符"覆盖"对此项无效
我实际上可以在不使用显式接口的情况下使用它,所以它实际上并没有阻止我,但我真的想知道,为了我自己的好奇心,如果想用显式接口做这个,那么正确的语法是什么?
显式接口实现不能是虚拟成员.请参阅C#语言规范的第13.4.1节(它已过时但在C#6.0中似乎没有更改此逻辑).特别:
显式接口成员实现包含访问修饰符是编译时错误,包含修饰符abstract,virtual,override或static是编译时错误.
这意味着,您永远无法直接覆盖此成员.
您可以做的解决方法是从显式实现中调用另一个虚方法:
class Base : IBla
{
void IBla.DoSomething()
{
this.DoSomethingForIBla();
}
protected virtual void DoSomethingForIBla()
{
...
}
}
class Derived : Base
{
protected override void DoSomethingForIBla()
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
我还遇到过这样的情况,我以为我想覆盖一个显式的接口实现并调用基类,并发现此问题及其答案为“无法完成”。
首先要注意的是,为了覆盖显式接口实现而无需调用基类,这是相当简单的。派生类仅需要实现接口本身。
public class ChildTest : ParentTest, ITest
{
string ITest.Speak()
{
return "Mooo";
}
// Note: any other interface functions will call ParentTest's implementation
}
Run Code Online (Sandbox Code Playgroud)
但是,现在没有“合法”的方法可以在类型的对象上调用ParentTest的实现,因为任何使用该接口的尝试都将导致调用的实现。ITest.SpeakChildTestChildTest
因此,只有对基本实现的调用才会引起复杂性。为了满足我的好奇心,我证明了可以做到,但实际上不应该...
保留基类不变,以下内容实际上允许使用反射调用基类。
public class ChildTest : ParentTest, ITest
{
string ITest.Speak()
{
return "Mooo" + typeof(ParentTest).GetMethod("ITest.Speak", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(this, new object[0]) as string;
}
}
Run Code Online (Sandbox Code Playgroud)
注意,如果示例代码包含在名称空间中,则需要标准接口名称。例如"MyNamespace.ITest.Speak"
如果该函数将被重复调用和/或针对许多对象被调用,则可以通过缓存方法信息和/或为基调用创建委托来提高性能,例如:
public class ChildTest : ParentTest, ITest
{
static ChildTest()
{
baseSpeakMethodInfo = typeof(ParentTest).GetMethod("ITest.Speak", BindingFlags.Instance | BindingFlags.NonPublic);
}
static private MethodInfo baseSpeakMethodInfo;
public ChildTest()
{
baseSpeak = baseSpeakMethodInfo.CreateDelegate(typeof(Func<string>), this) as Func<string>;
}
private Func<string> baseSpeak;
string ITest.Speak()
{
return "Mooo" + baseSpeak();
}
}
Run Code Online (Sandbox Code Playgroud)
与其他答案相比,它唯一的优势在于,如果您不能修改基类,它就可以工作。否则,这是一个可怕的解决方案,应该在基类中创建一种机制(与其他答案一样),以便为派生类提供一种合法的方法来调用基实现。
| 归档时间: |
|
| 查看次数: |
7851 次 |
| 最近记录: |