基于C#的接口基础教程之五
第五节 实现接口
显式实现接口成员
为了实现接口 类可以定义显式接口成员执行体(Explicit interface member implementations) 显式接口成员执行体可以是一个方法 一个属性 一个事件或者是一个索引指示器的定义 定义与该成员对应的全权名应保持一致
using System ; 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 就是显式接口成员执行体
说明
不能在方法调用 属性访问以及索引指示器访问中通过全权名访问显式接口成员执行体 事实上 显式接口成员执行体只能通过接口的实例 仅仅引用接口的成员名称来访问
显式接口成员执行体不能使用任何访问限制符 也不能加上abstract virtual override或static 修饰符
显式接口成员执行体和其他成员有着不同的访问方式 因为不能在方法调用 属性访问以及索引指示器访问中通过全权名访问 显式接口成员执行体在某种意义上是私有的 但它们又可以通过接口的实例访问 也具有一定的公有性质
只有类在定义时 把接口名写在了基类列表中 而且类中定义的全权名 类型和返回类型都与显式接口成员执行体完全一致时 显式接口成员执行体才是有效的 例如
class Shape: ICloneable { object ICloneable Clone( ) {…} int IComparable CompareTo(object other) {…} } 使用显式接口成员执行体通常有两个目的
因为显式接口成员执行体不能通过类的实例进行访问 这就可以从公有接口中把接口的实现部分单独分离开 如果一个类只在内部使用该接口 而类的使用者不会直接使用到该接口 这种显式接口成员执行体就可以起到作用
显式接口成员执行体避免了接口成员之间因为同名而发生混淆 如果一个类希望对名称和返回类型相同的接口成员采用不同的实现方式 这就必须要使用到显式接口成员执行体 如果没有显式接口成员执行体 那么对于名称和返回类型不同的接口成员 类也无法进行实现
下面的定义是无效的 因为Shape 定义时基类列表中没有出现接口IComparable
class Shape: ICloneable { object ICloneable Clone( ) {…} } class Ellipse: Shape { object ICloneable Clone( ) {…} }
在Ellipse 中定义ICloneable Clone是错误的 因为Ellipse即使隐式地实现了接口ICloneable ICloneable仍然没有显式地出现在Ellipse定义的基类列表中
接口成员的全权名必须对应在接口中定义的成员 如下面的例子中 Paint的显式接口成员执行体必须写成IControl Paint
using System ; interface IControl { void Paint( ) ; } interface ITextBox: IControl { void SetText(string text) ; } class TextBox: ITextBox { void IControl Paint( ) {…} void ITextBox SetText(string text) {…} }
实现接口的类可以显式实现该接口的成员 当显式实现某成员时 不能通过类实例访问该成员 而只能通过该接口的实例访问该成员 显式接口实现还允许程序员继承共享相同成员名的两个接口 并为每个接口成员提供一个单独的实现
下面例子中同时以公制单位和英制单位显示框的尺寸 Box类继承 IEnglishDimensions和 IMetricDimensions两个接口 它们表示不同的度量衡系统 两个接口有相同的成员名 Length 和 Width
程序清单 DemonInterface cs
interface IEnglishDimensions { float Length ( ) ; float Width ( ) ; } interface IMetricDimensions { float Length ( ) ; float Width ( ) ; } class Box : IEnglishDimensions IMetricDimensions { float lengthInches ; float widthInches ; public Box(float length float width) { lengthInches = length ; widthInches = width ; } float IEnglishDimensions Length( ) { return lengthInches ; } float IEnglishDimensions Width( ) { return widthInches ; } float IMetricDimensions Length( ) { return lengthInches * f ; } float IMetricDimensions Width( ) { return widthInches * f ; } public static void Main( ) { //定义一个实类对象 myBox : Box myBox = new Box( f f); // 定义一个接口 eDimensions :: IEnglishDimensions eDimensions = (IEnglishDimensions) myBox; IMetricDimensions mDimensions = (IMetricDimensions) myBox; // 输出: System Console WriteLine( Length(in): { } eDimensions Length( )); System Console WriteLine( Width (in): { } eDimensions Width( )); System Console WriteLine( Length(cm): { } mDimensions Length( )); System Console WriteLine( Width (cm): { } mDimensions Width( )); } }
输出 Length(in): Width (in): Length(cm): Width (cm):
代码讨论 如果希望默认度量采用英制单位 请正常实现 Length 和 Width 这两个方法 并从 IMetricDimensions 接口显式实现 Length 和 Width 方法
public float Length( ) { return lengthInches ; } public float Width( ) { return widthInches; } float IMetricDimensions Length( ) { return lengthInches * f ; } float IMetricDimensions Width( ) { return widthInches * f ; }
这种情况下 可以从类实例访问英制单位 而从接口实例访问公制单位
lishixinzhi/Article/program/net/201311/15704