对接口成员的访问2007-11-10 本站 对接口方法的调用和采用索引指示器访问的规则与类中的情况也是相同的。如果底层成员的命名与继承而来的高层成员一致,那么底层成员将覆盖同名的高层成员。但由于接口支持多继承,在多继承中,如果两个父接口含有同名的成员,这就产生了二义性(这也正是中取消了类的多继承机制的原因之一),这时需要进行显式的声明。程序清单15-2:
using System;interface ISequence{int Count{get;set;}}interface IRing{void count(int i);}interface IRingSequence:ISequence,IRing{}class C{void Test(IRingSequense rs){//rs.Count(1); 错误,Count有二义性//rs.Count=1; 错误,Count有二义性((ISequence)rs).Count=1; //正确((IRing)rs).Count(1); //正确调用IRing Count }}
上面的例子中,前两条语句x.Count(1)和x.Count=1会产生二义性,从而导致编译时错误,因此必须显式地给X指派父接口类型,这种指派在运行时不会带来额外的开销。再看下面的例子:程序清单15-3:
using System;interface IInteger{ void Add(int i);}interface IDouble{ void Add(double d);}interface INumber:IInteger,IDouble{}class C{ void Test(INumber n){ //n.Add(1);错误 n.Add(1.0); //正确((IInteger)n).Add(1); //正确((IDouble)n).Add(1); //正确 }}
调用n.Add(1)会产生二义性,因为候选的重载方法的参数类型均适用。但是,调用n.Add(1.0)是允许的,因为1.0是浮点数,参数类型与方法IInteger.Add()的参数类型不一致,这时只有IDouble.Add才是适用的。不过只要加入了显式的指派,就决不会产生二义性。接口的多重继承的问题也会带来成员访问上的问题。
interface IBase{ void F(int i);}interface ILeft:IBase{ new void F(int i);}interface IRight:IBase{ void G();}interface IDerived:ILeft,IRight{}class A{ void Test(IDerived d){ d.F(1);//调用ILeft.F ((IBase)d).F(1); //调用IBase.F ((ILeft)d).F(1); //调用ILeft.F ((IRight)d).F(1); //调用IBase.F }}
上例中,方法IBase.F在派生的接口ILeft中被ILeft的成员方法F覆盖了。所以对d.F(1)的调用实际上调用了。虽然从IBase----IRight---IDerived这条继承路径上来看,ILeft.F方法是没有被覆盖的。我们只要记住这一点:一旦成员被覆盖以后,所有对其的访问都被覆盖以后的成员“拦截”了。