1.1 接口实现
接口可以由类和结构来实现。为了指示类或结构实现了某接口,在该类或结构的基类列表中应该包含该接口的标识符。例如:
interface ICloneable
{
object Clone();
}
interface IComparable
{
int CompareTo(object other);
}
class ListEntry: ICloneable, IComparable
{
public object Clone() {...}
public int CompareTo(object other) {...}
}
如果一个类或结构实现某接口,则它还隐式实现该接口的所有基接口。即使在类或结构的基类列表中没有显式列出所有基接口,也是这样。例如:
interface IControl
{
void Paint();
}
interface ITextBox: IControl
{
void SetText(string text);
}
class TextBox: ITextBox
{
public void Paint() {...}
public void SetText(string text) {...}
}
在此,类 TextBox 同时实现了 IControl 和 ITextBox。
1.1.1 显式接口成员实现
为了实现接口,类或结构可以声明显式接口成员实现 (explicit interface member implementation)。显式接口成员实现就是一种方法、属性、事件或索引器声明,它使用完全限定接口成员名称作为标识符。例如
interface ICloneable
{
object Clone();
}
interface IComparable
{
int CompareTo(object other);
}
class ListEntry: ICloneable, IComparable
{
object ICloneable.Clone() {...}
int IComparable.CompareTo(object other) {...}
}
在此,ICloneable.Clone 和 IComparable.CompareTo 是显式接口成员实现。
某些情况下,接口成员的名称对于实现该接口的类可能是不适当的,此时,可以使用显式接口成员实现来实现该接口成员。例如,一个实现“文件抽象”的类一般会实现一个具有释放文件资源作用的 Close 成员函数,同时还可能使用显式接口成员实现来实现 IDisposable 接口的 Dispose 方法:
interface IDisposable
{
void Dispose();
}
class MyFile: IDisposable
{
void IDisposable.Dispose() {
Close();
}
public void Close() {
// Do what's necessary to close the file
System.GC.SuppressFinalize(this);
}
}
在方法调用、属性访问或索引器访问中,不能直接访问“显式接口成员实现”的成员,即使用它的完全限定名也不行。“显式接口成员实现”的成员只能通过接口实例访问,并且在通过接口实例访问时,只能用该接口成员的简单名称来引用。
显式接口成员实现中包含访问修饰符属于编译时错误,而且如果包含 abstract、virtual、override 或 static 修饰符也属于编译时错误。
显式接口成员实现具有与其他成员不同的可访问性特征。由于显式接口成员实现永远不能在方法调用或属性访问中通过它们的完全限定名来访问,因此,它们似乎是 private(私有的)。但是,因为它们可以通过接口实例来访问,所以它们似乎又是 public(公共的)。
显式接口成员实现有两个主要用途:
· 由于显式接口成员实现不能通过类或结构实例来访问,因此它们就不属于类或结构的自身的公共接口。当需在一个公用的类或结构中实现一些仅供内部使用(不允许外界访问)的接口时,这就特别有用。
· 显式接口成员实现可以消除因同时含有多个相同签名的接口成员所引起的多义性。如果没有显式接口成员实现,一个类或结构就不可能为具有相同签名和返回类型的接口成员分别提供相应的实现,也不可能为具有相同签名和不同返回类型的所有接口成员中的任何一个提供实现。
为了使显式接口成员实现有效,声明它的类或结构必须在它的基类列表中指定一个接口,而该接口必须包含一个成员,该成员的完全限定名、类型和参数类型与该显式接口成员实现所具有的完全相同。因此,在下列类中
class Shape: ICloneable
{
object ICloneable.Clone() {...}
int IComparable.CompareTo(object other) {...} // invalid
}
IComparable.CompareTo 声明将导致编译时错误,原因是 IComparable 未列在 Shape 的基类列表中,并且不是 ICloneable 的基接口。与此类似,在下列声明中
class Shape: ICloneable
{
object ICloneable.Clone() {...}
}
class Ellipse: Shape
{
object ICloneable.Clone() {...} // invalid
}
Ellipse 中的 ICloneable.Clone 声明也将导致编译时错误,因为 ICloneable 未在 Ellipse 的基类列表中显式列出。
接口成员的完全限定名必须引用声明该成员的接口。因此,下列声明中
interface IControl
{
void Paint();
}
interface ITextBox: IControl
{
void SetText(string text);
}
class TextBox: ITextBox
{
void IControl.Paint() {...}
void ITextBox.SetText(string text) {...}
}
Paint 的显式接口成员实现必须写为 IControl.Paint。
1.1.2 接口映射
类或结构必须为它的基类列表中所列出的接口的所有成员提供它自己的实现。在进行实现的类或结构中定位接口成员的实现的过程称为接口映射 (interface mapping)。
关于类或结构 C 的接口映射就是查找 C 的基类列表中指定的每个接口的每个成员的实现。对某个特定接口成员 I.M 的实现(其中 I 是声明了成员 M 的接口)的定位按下述规则执行:从 C 开始,按继承顺序,逐个检查它的每个后续基类(下面用 S 表示每个进行检查的类或结构),直到找到匹配项:
评论