对于接口(interface)而言,添加abstract
甚至是public
关键字都是多余的,因此你可以省略它们:
interface MyInterface {
void Method();
}
在CIL中,该方法被标记为
virtual
和
abstract
。(请注意,Java允许声明接口成员为
public abstract
。)
对于实现类,有一些选择:
不可重写:在C#中,类没有将该方法声明为
virtual
。这意味着它不能在派生类中被重写(只能被隐藏)。在CIL中,该方法仍然是虚拟的(但是被封闭),因为它必须支持与接口类型相关的多态性。
class MyClass : MyInterface {
public void Method() {}
}
可重写的:在C#和CIL中,该方法是virtual
。它参与多态分派并且可以被覆盖。
class MyClass : MyInterface {
public virtual void Method() {}
}
显式接口实现:这是一种类实现接口但不在类的公共接口中提供接口方法的方式。在CIL中,该方法将是private
类型的,但仍然可以通过对应接口类型的引用从类外部调用它。显式实现也是不可重写的。这是因为存在一个CIL指令(.override
),它将把私有方法链接到正在实现的相应接口方法。
[C#]
class MyClass : MyInterface {
void MyInterface.Method() {}
}
[CIL]
.method private hidebysig newslot virtual final instance void MyInterface.Method() cil managed
{
.override MyInterface::Method
}
在 VB.NET 中,你甚至可以在实现类中为接口方法命名别名。
Public Class MyClass
Implements MyInterface
Public Sub AliasedMethod() Implements MyInterface.Method
End Sub
End Class
[CIL]
.method public newslot virtual final instance void AliasedMethod() cil managed
{
.override MyInterface::Method
}
现在,考虑这个奇怪的情况:
interface MyInterface {
void Method();
}
class Base {
public void Method();
}
class Derived : Base, MyInterface { }
如果在同一个程序集中声明了
Base
和
Derived
,即使
Base
没有实现接口,编译器也会使
Base::Method
在CIL中变成虚拟的并且被标记为sealed。
如果在不同的程序集中声明了
Base
和
Derived
,编译
Derived
程序集时,编译器不会更改其他程序集,因此它会引入
Derived
中的一个成员,该成员将是一个显式实现
MyInterface::Method
,仅将调用委托给
Base::Method
。
因此,你会发现
每个接口方法的实现都必须支持多态行为,并且必须在CIL上标记为virtual,即使编译器必须通过各种方式来实现。