上一篇 | 下一篇

基于C#的接口基础教程之四

发布: 2008-6-30 09:07 | 作者: admin | 来源: | 查看: 0次

作者:佚名 文章来源:不详 点击数: 更新时间:2006-6-15

  第四节、访问接口

  对接口成员的访问

  对接口方法的调用和采用索引指示器访问的规则与类中的情况也是相同的。如果底层成员的命名与继承而来的高层成员一致,那么底层成员将覆盖同名的高层成员。但由于接口支持多继承,在多继承中,如果两个父接口含有同名的成员,这就产生了二义性(这也正是C#中取消了类的多继承机制的原因之一),这时需要进行显式的定义:

using System ;

interface ISequence {

 int Count { get; set; }

}

interface IRing {

 void Count(int i) ;

}

interface IRingSequence: ISequence, IRing { }

 class CTest {

  void Test(IRingSequence rs) {

   //rs.Count(1) ; 错误, Count 有二义性

   //rs.Count = 1; 错误, Count 有二义性

   ((ISequence)rs).Count = 1; // 正确

   ((IRing)rs).Count(1) ; // 正确调用IRing.Count

  }

}

  上面的例子中,前两条语句rs .Count(1)和rs .Count = 1会产生二义性,从而导致编译时错误,因此必须显式地给rs 指派父接口类型,这种指派在运行时不会带来额外的开销。

  再看下面的例子:

using System ;

interface IInteger {

 void Add(int i) ;

}

interface IDouble {

 void Add(double d) ;

}

interface INumber: IInteger, IDouble {}

 class CMyTest {

 void Test(INumber Num) {

  // Num.Add(1) ; 错误

  Num.Add(1.0) ; // 正确

  ((IInteger)n).Add(1) ; // 正确

  ((IDouble)n).Add(1) ; // 正确

 }

}

  调用Num.Add(1) 会导致二义性,因为候选的重载方法的参数类型均适用。但是,调用Num.Add(1.0) 是允许的,因为1.0 是浮点数参数类型与方法IInteger.Add()的参数类型不一致,这时只有IDouble.Add 才是适用的。不过只要加入了显式的指派,就决不会产生二义性。

  接口的多重继承的问题也会带来成员访问上的问题。例如:

interface IBase {

 void FWay(int i) ;

}

interface ILeft: IBase {

 new void FWay (int i) ;

}

interface IRight: IBase

{ void G( ) ; }

interface IDerived: ILeft, IRight { }

class CTest {

 void Test(IDerived d) {

  d. FWay (1) ; // 调用ILeft. FWay

  ((IBase)d). FWay (1) ; // 调用IBase. FWay

  ((ILeft)d). FWay (1) ; // 调用ILeft. FWay

  ((IRight)d). FWay (1) ; // 调用IBase. FWay

 }

}

  上例中,方法IBase.FWay在派生的接口ILeft中被Ileft的成员方法FWay覆盖了。所以对d. FWay (1)的调用实际上调用了。虽然从IBase-> IRight-> IDerived这条继承路径上来看,ILeft.FWay方法是没有被覆盖的。我们只要记住这一点:一旦成员被覆盖以后,所有对其的访问都被覆盖以后的成员"拦截"了。

  类对接口的实现

  前面我们已经说过,接口定义不包括方法的实现部分。接口可以通过类或结构来实现。我们主要讲述通过类来实现接口。用类来实现接口时,接口的名称必须包含在类定义中的基类列表中。

  下面的例子给出了由类来实现接口的例子。其中ISequence 为一个队列接口,提供了向队列尾部添加对象的成员方法Add( ),IRing 为一个循环表接口,提供了向环中插入对象的方法Insert(object obj),方法返回插入的位置。类RingSquence 实现了接口ISequence 和接口IRing。

using System ;

interface ISequence {

 object Add( ) ;

}

interface ISequence {

 object Add( ) ;

}

interface IRing {

 int Insert(object obj) ;

}

class RingSequence: ISequence, IRing

{

 public object Add( ) {…}

 public int Insert(object obj) {…}

}

  如果类实现了某个接口,类也隐式地继承了该接口的所有父接口,不管这些父接口有没有在类定义的基类表中列出。看下面的例子:

using System ;

interface IControl {

 void Paint( );

}

interface ITextBox: IControl {

 void SetText(string text);

}

interface IListBox: IControl {

 void SetItems(string[] items);

}

interface IComboBox: ITextBox, IListBox { }

  这里, 接口IcomboBox继承了ItextBox和IlistBox。类TextBox不仅实现了接口ITextBox,还实现了接口ITextBox 的父接口IControl。

字号: | 推荐给好友

21/212>

评分:0

我来说两句