c语言接口与实现:C#访问接口



第 4节、访问接口

  对接口成员访问

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



using;
erfaceISequence{
 Count{get;;}
}
erfaceIRing{
 voidCount(i);
}
erfaceIRingSequence:ISequence,IRing{}
 CTest{
  voidTest(IRingSequencers){
   //rs.Count(1);,Count有 2义性
   //rs.Count=1;,Count有 2义性
   ((ISequence)rs).Count=1;//正确
   ((IRing)rs).Count(1);//正确IRing.Count
  }
}

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

  再看下面例子:

using;
erfaceIInteger{
 voidAdd(i);
}
erfaceIDouble{
 voidAdd(doubled);
}
erfaceINumber:IInteger,IDouble{}
 CMyTest{
 voidTest(INumberNum){
  //Num.Add(1);
  Num.Add(1.0);//正确
  ((IInteger)n).Add(1);//正确
  ((IDouble)n).Add(1);//正确
 }
}

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

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

erfaceIBase{
 voidFWay(i);
}
erfaceILeft:IBase{
 voidFWay(i);
}
erfaceIRight:IBase
{voidG;}
erfaceIDerived:ILeft,IRight{}
CTest{
 voidTest(IDerivedd){
  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为个队列接口提供了向队列尾部添加对象成员思路方法AddIRing为个循环表接口提供了向环中插入对象思路方法Insert(objectobj)思路方法返回插入位置类RingSquence实现了接口ISequence和接口IRing

using;
erfaceISequence{
 objectAdd;
}
erfaceISequence{
 objectAdd;
}
erfaceIRing{
 Insert(objectobj);
}
RingSequence:ISequence,IRing
{
 publicobjectAdd{…}
 publicInsert(objectobj){…}
}  如果类实现了某个接口类也隐式地继承了该接口所有父接口不管这些父接口有没有在类定义基类表中列出看下面例子:

using;
erfaceIControl{
 voidPa;
}
erfaceITextBox:IControl{
 voidSetText(text);
}


erfaceIListBox:IControl{
 voidSetItems(items);
}
erfaceIComboBox:ITextBox,IListBox{}

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

  前面我们已经看到个类可以实现多个接口再看下面例子:

erfaceIDataBound{
 voidBind(Binderb);
}
publicEditBox:Control,IControl,IDataBound{
 publicvoidPa;
 publicvoidBind(Binderb){...}
}

  类EditBox从类Control中派生并且实现了Icontrol和IdataBound在前面例子中接口Icontrol中Pa思路方法和IdataBound接口中Bind思路方法都用类EditBox中公共成员实现C#提供种实现这些思路方法可选择途径这样可以使执行这些类避免把这些成员设定为公共接口成员可以用有效名称来实现例如类EditBox可以改作思路方法Icontrol.Pa和IdataBound.Bind来来实现

publicEditBox:IControl,IDataBound{
 voidIControl.Pa{...}
 voidIDataBound.Bind(Binderb){...}
}

  通过外部指派接口成员实现了每个成员所以用这种思路方法实现成员称为外部接口成员外部接口成员可以只是通过接口来例如Pa思路方法中EditBox实现可以只是通过创建Icontrol接口来

Test{
 voidMain{
  EditBoxeditbox=EditBox;
  editbox.Pa;//:EditBox没有Pa事件
  IControlcontrol=editbox;
  control.Pa;//EditBoxPa事件
 }
}

  上例中类EditBox从Control类继承并同时实现了IControlandIDataBound接口EditBox中Pa思路方法来自IControl接口Bind思路方法来自IDataBound接口 2者在EditBox类中都作为公有成员实现当然在C#中我们也可以选择不作为公有成员实现接口

  如果每个成员都明显地指出了被实现接口通过这种途径被实现接口我们称的为显式接口成员(expliciterfacemember)用这种方式我们改写上面例子:

publicEditBox:IControl,IDataBound{
 voidIControl.Pa{…}
 voidIDataBound.Bind(Binderb){…}
}

  显式接口成员只能通过接口例如:

CTest{
 voidMain{
  EditBoxeditbox=EditBox;
  editbox.Pa;//:区别思路方法
  IControlcontrol=editbox;
  control.Pa;//EditBoxPa思路方法
 }
}

  上述代码中对editbox.Paeditbox本身并没有提供这思路方法control.Pa是正确方式

  注释:接口本身不提供所定义成员实现它仅仅介绍说明这些成员这些成员必须依靠实现接口类或其它接口支持

  知道了怎样访问接口我们还要知道怎样实现接口,要实现C#接口请看下节-实现接口
Tags:  c接口函数 c语言接口 c接口 c语言接口与实现

延伸阅读

最新评论

发表评论