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 就是显式接口成员执行体。
说明:
1、不能在方法调用、属性访问以及索引指示器访问中通过全权名访问显式接口成员执行体。事实上,显式接口成员执行体只能通过接口的实例,仅仅引用接口的成员名称来访问。
2、显式接口成员执行体不能使用任何访问限制符,也不能加上abstract, virtual, override或static 修饰符。
3、显式接口成员执行体和其他成员有着不同的访问方式。因为不能在方法调用、属性访问以及索引指示器访问中通过全权名访问,显式接口成员执行体在某种意义上是私有的。但它们又可以通过接口的实例访问,也具有一定的公有性质。
4、只有类在定义时,把接口名写在了基类列表中,而且类中定义的全权名、类型和返回类型都与显式接口成员执行体完全一致时,显式接口成员执行体才是有效的,例如:
class Shape: ICloneable { object ICloneable.Clone( ) {…} int IComparable.CompareTo(object other) {…} } |
class Shape: ICloneable { object ICloneable.Clone( ) {…} } class Ellipse: Shape { object ICloneable.Clone( ) {…} } |
using System ; interface IControl { void Paint( ) ; } interface ITextBox: IControl { void SetText(string text) ; } class TextBox: ITextBox { void IControl.Paint( ) {…} void ITextBox.SetText(string text) {…} } |
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 * 2.54f ; } float IMetricDimensions.Width( ) { return widthInches * 2.54f ; } public static void Main( ) { //定义一个实类对象 "myBox":: Box myBox = new Box(30.0f, 20.0f); // 定义一个接口" eDimensions":: IEnglishDimensions eDimensions = (IEnglishDimensions) myBox; IMetricDimensions mDimensions = (IMetricDimensions) myBox; // 输出: System.Console.WriteLine(" Length(in): {0}", eDimensions.Length( )); System.Console.WriteLine(" Width (in): {0}", eDimensions.Width( )); System.Console.WriteLine(" Length(cm): {0}", mDimensions.Length( )); System.Console.WriteLine(" Width (cm): {0}", mDimensions.Width( )); } } |
public float Length( ) { return lengthInches ; } public float Width( ){ return widthInches; } float IMetricDimensions.Length( ) { return lengthInches * 2.54f ; } float IMetricDimensions.Width( ) { return widthInches * 2.54f ; } |
System.Console.WriteLine("Length(in): {0}", myBox.Length( )) ; System.Console.WriteLine("Width (in): {0}", myBox.Width( )) ; System.Console.WriteLine("Length(cm): {0}", mDimensions.Length( )) ; System.Console.WriteLine("Width (cm): {0}", mDimensions.Width( )) ; |
using System ; interface IControl { void Paint( ) ; } interface ITextBox: IControl { void SetText(string text) ; } interface IListBox: IControl { void SetItems(string[] items) ; } interface IComboBox: ITextBox, IListBox { } |
interface IControl { void Paint( ); } class Control: IControl { public void Paint( ) {...} } class TextBox: Control { new public void Paint( ) {...} } |
Control c = new Control( ) ; TextBox t = new TextBox( ) ; IControl ic = c ; IControl it = t ; c.Paint( ) ; // 影响Control.Paint( ) ; t.Paint( ) ; // 影响TextBox.Paint( ) ; ic.Paint( ) ; // 影响Control.Paint( ) ; it.Paint( ) ; // 影响Control.Paint( ) ; |
interface IControl { void Paint( ) ; } class Control: IControl { public virtual void Paint( ) {...} } class TextBox: Control { public override void Paint( ) {...} } |
Control c = new Control( ) ; TextBox t = new TextBox( ) ; IControl ic = c ; IControl it = t ; c.Paint( ) ; // 影响Control.Paint( ); t.Paint( ) ; // 影响TextBox.Paint( ); ic.Paint( ) ; // 影响Control.Paint( ); it.Paint( ) ; // 影响TextBox.Paint( ); |
interface IControl { void Paint( ) ; } class Control: IControl { void IControl.Paint( ) { PaintControl( ); } protected virtual void PaintControl( ) {...} } class TextBox: Control { protected override void PaintControl( ) {...} } |
这里,从Control 继承的类可以通过覆盖方法PaintControl 来对IControl.Paint 的实现程序进行特殊化。
精品教程尽在w ww.xvna.com
3、重新实现接口
我们已经介绍过,派生类可以对基类中已经定义的成员方法进行重载。类似的概念引入到类对接口的实现中来,叫做接口的重实现(re-implementation)。继承了接口实现的类可以对接口进行重实现。这个接口要求是在类定义的基类列表中出现过的。对接口的重实现也必须严格地遵守首次实现接口的规则,派生的接口映射不会对为接口的重实现所建立的接口映射产生任何影响。
下面的代码给出了接口重实现的例子:
interface IControl { void Paint( ) ; class Control: IControl void IControl.Paint( ) {…} class MyControl: Control, IControl public void Paint( ) {} } |
using System ; interface IMethods { void F( ) ; void G( ) ; void H( ) ; void I( ) ; } class Base: IMethods { void IMethods.F( ) { } void IMethods.G( ) { } public void H( ) { } public void I( ) { } } class Derived: Base, IMethods { public void F( ) { } void IMethods.H( ) { } } |
using System ; interface IBase { void F( ) ; } interface IDerived: IBase { void G( ) ; } class C: IDerived { void IBase.F( ) { //对F 进行实现的代码… } void IDerived.G( ) { //对G 进行实现的代码… } } class D: C, IDerived { public void F( ) { //对F 进行实现的代码… } public void G( ) { //对G 进行实现的代码… } } |
4、映射接口
类必须为在基类表中列出的所有接口的成员提供具体的实现。在类中定位接口成员的实现称之为接口映射(interface mapping )。
映射,数学上表示一一对应的函数关系。接口映射的含义也是一样,接口通过类来实现,那么对于在接口中定义的每一个成员,都应该对应着类的一个成员来为它提供具体的实现。
类的成员及其所映射的接口成员之间必须满足下列条件:
1、如果A和B都是成员方法,那么A和B的名称、类型、形参表(包括参数个数和每一个参数的类型)都应该是一致的。
2、如果A和B都是属性,那么A和B的名称、类型应当一致,而且A和B的访问器也是类似的。但如果A不是显式接口成员执行体,A允许增加自己的访问器。
3、如果A和B都是时间那么A和B的名称、类型应当一致。
4、如果A和B都是索引指示器,那么A和B的类型、形参表(包括参数个数和每一个参数的类型)应当一致。而且A和B的访问器也是类似的。但如果A不是显式接口成员执行体,A允许增加自己的访问器。
那么,对于一个接口成员,怎样确定由哪一个类的成员来实现呢?即一个接口成员映射的是哪一个类的成员?在这里,我们叙述一下接口映射的过程。假设类C实现了一个接口IInterface,Member是接口IInterface中的一个成员,在定位由谁来实现接口成员Member,即Member的映射过程是这样的:
1、如果C中存在着一个显式接口成员执行体,该执行体与接口IInterface 及其成员Member相对应,则由它来实现Member 成员。
2、如果条件(1)不满足,且C中存在着一个非静态的公有成员,该成员与接口成员Member相对应,则由它来实现Member 成员。
3、如果上述条件仍不满足,则在类C定义的基类列表中寻找一个C 的基类D,用D来代替C。
4、重复步骤1-- 3 ,遍历C的所有直接基类和非直接基类,直到找到一个满足条件的类的成员。
5、如果仍然没有找到,则报告错误。
下面是一个调用基类方法来实现接口成员的例子。类Class2 实现了接口Interface1,类Class2 的基类Class1 的成员也参与了接口的映射,也就是说类Class2 在对接口Interface1进行实现时,使用了类Class1提供的成员方法F来实现接口Interface1的成员方法F:
interface Interface1 { void F( ) ; } class Class1 { public void F( ) { } public void G( ) { } } class Class2: Class1, Interface1 { new public void G( ) {} } |
在进行接口映射时,还要注意下面两点:
1、在决定由类中的哪个成员来实现接口成员时,类中显式说明的接口成员比其它成员优先实现。
2、使用Private、protected和static修饰符的成员不能参与实现接口映射。例如:
interface ICloneable { object Clone( ) ; } class C: ICloneable { object ICloneable.Clone( ) {…} public object Clone( ) {…} } |
interface IControl { void Paint( ) ; } interface IForm { void Paint( ) ; } class Page: IControl, IForm { public void Paint( ) {…} } |
interface IControl { void Paint( ) ; } interface IForm { void Paint( ) ; } class Page: IControl, IForm { public void IControl.Paint( ) { //具体的接口实现代码 } public void IForm.Paint( ) { //具体的接口实现代码 } } |
interface IBase { int P { get; } } interface IDerived: IBase { new int P( ) ; } |
//一:对两个接口成员都采用显式接口成员执行体来实现 lass C: IDerived { int IBase.P get { //具体的接口实现代码 } int IDerived.P( ){ //具体的接口实现代码 } } //二:对Ibase 的接口成员采用显式接口成员执行体来实现 class C: IDerived { int IBase.P get {//具体的接口实现代码} public int P( ){ //具体的接口实现代码 } } //三:对IDerived 的接口成员采用显式接口成员执行体来实现 class C: IDerived{ public int P get {//具体的接口实现代码} int IDerived.P( ){ //具体的接口实现代码} } |
using System ; interface IControl { void Paint( ) ; interface ITextBox: IControl { void SetText(string text) ; } interface IListBox: IControl { void SetItems(string[] items) ; } class ComboBox: IControl, ITextBox, IListBox { void IControl.Paint( ) {…} void ITextBox.SetText(string text) {…} void IListBox.SetItems(string[] items) {…} } |