新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     >>计算机科学论坛<<     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论.NET,C#,ASP,VB技术
    [返回] 计算机科学论坛计算机技术与应用『 Dot NET,C#,ASP,VB 』 → 基于C#的接口基础教程之四 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 2762 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 基于C#的接口基础教程之四 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 Dot NET,C#,ASP,VB 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 基于C#的接口基础教程之四


      第四节、访问接口

      对接口成员的访问

      对接口方法的调用和采用索引指示器访问的规则与类中的情况也是相同的。如果底层成员的命名与继承而来的高层成员一致,那么底层成员将覆盖同名的高层成员。但由于接口支持多继承,在多继承中,如果两个父接口含有同名的成员,这就产生了二义性(这也正是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。

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

    interface IDataBound {
     void Bind(Binder b);
    }
    public class EditBox: Control, IControl, IDataBound {
     public void Paint( );
     public void Bind(Binder b) {...}
    }  

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

    public class EditBox: IControl, IDataBound {
     void IControl.Paint( ) {...}
     void IDataBound.Bind(Binder b) {...}
    }

      因为通过外部指派接口成员实现了每个成员,所以用这种方法实现的成员称为外部接口成员。外部接口成员可以只是通过接口来调用。例如,Paint方法中EditBox的实现可以只是通过创建Icontrol接口来调用。

    class Test {
     static void Main( ) {
      EditBox editbox = new EditBox( );
      editbox.Paint( ); //错误: EditBox 没有Paint 事件
      IControl control = editbox;
      control.Paint( ); // 调用 EditBox的Paint事件
     }
    }

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

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

    public class EditBox: IControl, IDataBound {
     void IControl.Paint( ) {…}
     void IDataBound.Bind(Binder b) {…}
    }

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

    class CTest {
     static void Main( ) {
      EditBox editbox = new EditBox( ) ;
      editbox.Paint( ) ; //错误:不同的方法
      IControl control = editbox;
      control.Paint( ) ; //调用 EditBox的Paint方法
     }
    }

      上述代码中对editbox.Paint( )的调用是错误的,因为editbox 本身并没有提供这一方法。control.Paint( )是正确的调用方式。

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

      知道了怎样访问接口,我们还要知道怎样实现接口,要实现C#的接口,请看下一节-实现接口


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/3/4 11:32:00
     
     inzaghiguo 美女呀,离线,快来找我吧!
      
      
      等级:大一(高数修炼中)
      文章:12
      积分:106
      门派:XML.ORG.CN
      注册:2005/4/11

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给inzaghiguo发送一个短消息 把inzaghiguo加入好友 查看inzaghiguo的个人资料 搜索inzaghiguo在『 Dot NET,C#,ASP,VB 』的所有贴子 引用回复这个贴子 回复这个贴子 查看inzaghiguo的博客2
    发贴心情 
    看看看
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/4/20 11:01:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 Dot NET,C#,ASP,VB 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2025/7/29 17:22:56

    本主题贴数2,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    109.375ms