[英]Why doesn't C# support explicitly implemented virtual methods?
C# 中的接口方法可以显式实现,以便在将实例显式转换为接口类型时调用它们的实现。 为什么类的虚拟方法也不支持这一点?
尽管解决“多重继承”问题是接口所独有的,但似乎由于显式实现的成员对接口有用的所有其他原因,它们对虚拟方法也很有用。 一个更干净的返回型协方差 model 浮现在脑海中。
编辑:根据要求,一个例子:
public class Foo {
...
}
public class Bar : Foo {
...
}
class Base {
abstract Foo A ();
}
class Dervied {
private Bar _b;
Bar A () {
return _b;
}
Foo Base.A () {
return _b;
}
}
我知道使用辅助方法来模拟这一点,但最终效果似乎具有显式实现所具有的任何不良特征,但 API 更脏。 我的问题的症结不是如何进行返回类型协方差,而是为什么虚拟方法不支持类似的接口机制。
有些人建议首先不要使用public virtual
方法。 而是创建一个表示使用者接口的public
非虚拟方法和一个表示实现者接口的protected virtual
方法。
我不会将调用者和实施者的合同分开称为“混淆设计”。 在许多情况下,它更清洁 IMO,但我通常懒得实际这样做。
这种设计在返回类型协方差和方法隐藏方面效果更好。
这样做的另一个好处是public
包装器可以添加额外的检查代码并支持调用者和实现者的不同合约。
我如何模拟返回类型协方差的一个例子:
public class Base
{
protected virtual Base FooOverride(int i){return new Base();};//FooOverride does not need to duplicate the argument checking
public Base Foo(int i)
{
if(i<0)
throw new ArgumentException("i<0");
return FooOverride(i);
}
}
public class Derived:Base
{
protected override Base FooOverride(int i){return new Derived();};
public new Derived Foo(int i)
{
return (Derived)base.Foo();
}
}
除了允许这样的事情之外,这还有什么好处?
class Base
{
virtual void M() { }
}
class Derived : Base
{
override void M() { }
override void Base.M() { }
}
这有效地将违反Liskov 替换原则纳入 C# 语言 - 如果我有一个 Base 类型的变量,则根据运行时类型是 Base 还是 Derived,对其调用 M() 可以做完全不同的事情。
显式接口实现是不同的。 假设你有这个:
interface IFoo
{
void DoStuff();
}
interface IBar
{
void DoStuff();
}
class C : IFoo, IBar
{
void IFoo.DoStuff() { }
void IBar.DoStuff() { }
}
这保留了 LSP - 如果我有一个恰好是运行时类型 C 的 IFoo 变量,则在其上调用 DoStuff() 将获得它的 IFoo 实现。 IBar 也是如此。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.