我有两节课:
public class Question : IDisposable, IEquatable<Question>
{
}
public class SessionQuestion : Question, IDisposable, IEquatable<SessionQuestion>
{
}
Run Code Online (Sandbox Code Playgroud)
作为Question继承IDisposable和IEquatable,是否也SessionQuestion隐式继承了这些接口?
小智 6
答案是"是" - 接口是继承的.但是,是否可以省略包含类中的接口定义取决于该类是否希望将某些接口成员作为显式接口实现.
让我们来看看这个非常简单(而且很愚蠢)的例子:
public interface IMyInterface
{
void foo();
}
public class A : IMyInterface
{
public void foo()
{
Console.Out.WriteLine("A.foo() executed");
}
}
public class B : A, IMyInterface
{
void IMyInterface.foo()
{
Console.Out.WriteLine("B.foo() executed");
}
}
Run Code Online (Sandbox Code Playgroud)
由于B希望将foo()方法作为显式接口实现,因此必须将IMyInterface接口指定为其类定义的一部分 - 即使类A已经实现了此接口.在这种情况下,从基类继承接口声明是不够的.
如果B类没有显式接口实现,那么B类不需要再次指定接口(在这个小例子中为IMyInterface).
从基类继承接口并为该接口的成员提供一些显式接口实现可能会产生最多令人惊讶的效果,并且最坏的情况可能导致软件损坏/错误.
如果执行以下代码序列:
A obj = new A();
obj.foo();
IMyInterface x = obj;
x.foo();
Run Code Online (Sandbox Code Playgroud)
输出将是
A.foo()执行
A.foo()执行
但是,现在让我们使用类型B的对象,否则保持代码完全相同:
B obj = new B();
obj.foo();
IMyInterface x = obj;
x.foo();
Run Code Online (Sandbox Code Playgroud)
输出会有所不同:
A.foo()执行
B.foo()执行
为什么会这样?请记住,B类继承了A类中foo()方法的实现.因此,调用obj.foo()仍然会执行继承的foo()方法.
那么,为什么x.foo()不调用A类提供的foo()实现呢?或者,为什么obj.foo()不调用为B类中的foo()提供的实现?
因为x是IMyInterface类型的变量,所以由类型B的对象提供的foo()方法的显式接口实现在调用时优先x.foo().可变OBJ是不类型的IMyInterface的,因此obj.foo()将不调用的显式接口实现FOO()方法.
由于这些令人惊讶的结果,很容易理解为什么在大多数情况下,已经由基类实现的接口的显式接口实现确实是一个坏主意.俗话说:只因为你不能意味着你应该这样做.