DEITY's profileScorDeity@雾霭无痕.天蝎恶魔PhotosBlogLists Tools Help

Blog


    December 25

    接口的终结解释

    http://club.sooyie.com/blogs/wuzi/archive/2006/10/09/_A563E3538476C87ED37EE389CA91_-.aspx
      简单的说接口就是一个契约或者规范。比如遥控器,国家出台了一个国家遥控器规范,明文要求所有的遥控器厂家都要遵循这个规范,如果不遵循规范就不给3C认证标志,就不允许上市出卖。为什么要这个规范呢?大家在时间生活中会经常碰到,甲厂的遥控器不能遥控乙厂的电视,电视遥控器不能遥控其它电器如空调,冰箱!原因是什么呢?是各个遥控器都没有遵循一个规范,电波有长有短,电压有高有低,导致各自为政,四分五裂。
      可以想像出国家遥控器标准只是是规定遥控器的一些重要技术指标,比如要发射波应该多长,电压应该多高……但它绝对不会规范出遥控器的材质、形状、重量和颜色,也就是说规范把所有同遥控无关的东西都抛弃了!每个遥控器厂家只要遵循了规范,那么对遥控器可以有任意的诠释。比如A厂可以用铁做,牢固无比,B厂可以用纸,可以任意折叠,anyway,不管用什么做,做出什么样子,只要遵循规范的遥控器就可以遥控所有的电器(当然电器厂家也要遵循一定的规范),甚至可以遥控导弹发射!利害吧,这就是接口的威力!
    再详细点,接口就是一个规范,他和具体的实现无关!接口是规范(虚的),他只是一张纸,也是说在实际的使用中接口只有依托一个实现了它的类的实例,才会有意义,如上面的各个厂家做的遥控器产品。每个实现接口的类(厂家)必需实现接口中所有的功能。一旦一个类实现了一个接口,就可说一个类和接口捆绑了(这个很重要,做题目的时候会用到)

      来个例子
        interface 遥控器规范    //国家定义的遥控器规范,每个遥控器厂家必需实现(诠释)它
        {
              int 波长();
              int 电压();
        }
        class 甲厂铁遥控器 : 遥控器规范    //甲厂的遥控器实现(诠释)了这个规范,它和遥控器规范捆绑了!好,它可以在市场上出售了
        {
              public int 波长();                        //规范上定义的指标
              public int 电压();                        //规范上定义的指标
              public int 形状() { 正方形 };              //甲厂自己对该产品的诠释
              public int 材质() { 铁 };                  //甲厂自己对该产品的诠释
        }
        class 乙厂纸遥控器 : 遥控器规范    //甲厂的遥控器实现(诠释)了这个规范,它和遥控器规范捆绑了!好,它可以在市场上出售了
        {
              public  int  波长();                      //规范上定义的指标 
              public  int  电压();                      //规范上定义的指标       
              public  int  形状() { 圆形 };             //甲厂自己对该产品的诠释,是圆形
              public  int  材质() { 纸 };              //甲厂自己对该产品的诠释,用纸做,好酷!     
        }
        class 电器
        { procedure 接收遥控(遥控器规范)    //电器上,接收遥控指令
            {.....
                  接收(遥控器规范.波长)  ;             
                  接收(遥控器规范.电压);
                  .....}      }   
        static  main()
        {
            甲厂铁遥控器    ControlA    ;    //申明控制器对象
            乙厂纸遥控器    ControlB    ;
            ControlA    =  new  甲厂铁遥控器();  //实例化控制器对象,这个时候系统在托管堆中为该对象分配了空间
            ControlB    =  new  乙厂纸遥控器()  ;
            遥控器规范    ControlInterfaceA  =  (遥控器规范)遥控器1  ;    //把对象实例转换成一个规范,为什么呢?因为"我家的电器".只能识别遥控器规范,它识别不到具体的遥控器
            遥控器规范    ControlInterfaceB  =  (遥控器规范)遥控器2;    //同上
            电器    我家的电器  =  new  电器();
            我家的电器.接收遥控(ControlInterfaceA)    //我用甲厂遥控器遥控我家的电器.  注意:  这里的ControlInterfaceA是不能单独存在的,它必要依赖实现了"遥控器规范"的类的实例"ControlA".道理很简单,接口是一个指针,不会被分配空间,你就无法使用,只有和一个具体类的实例联系了,才有了可以活跃空间.
            我家的电器.接收遥控(ControlInterfaceB)    //我用乙厂遥控器遥控我家的电器
           
            ...
            //下面是我的的想像,我可以用遥控器来控制导弹发射!
            我的导弹.接收遥控(ControlInterfaceA);
            我的导弹.接收遥控(ControlInterfaceB);       
            ...
        }
    --------------------------------------------------------------------
    接口的执行
      好了,有了接口的概念,再来谈 C# 程序在运行中是如何使用接口的,如何访问接口函数。具体流程如下
      A、当调用一个接口的函数时,系统会去检查这个接口对应实例是什么。
      B、找到这个实例后,再去找这个实例对应的实例类是什么。
      C、根据这个实例类去检查该实例类是否和接口发生了捆绑(看是否实现了该接口,冒号后面就是)
      D、好!如果实例类实现了该接口(发生了捆绑),它就在这个实例类中找函数的定义。然后执行该函数。执行结束。
      E、如果没找到,他就继续往父类找,直到找到第一个和接口捆绑的父类为止。
      F、找到后,它再检查该函数是否是虚拟函数。
      G、如果不是,他马上就执行它。
    H、如果是,麻烦了,系统又要从头来过,去检查该实例类的函数是否重载了该函数。

    例子:

    using System;

    namespace ConsoleApplication1
    {
     /**//// <summary>
     /// Class1 的摘要说明。
     /// </summary>
     public interface  I
     {
      void  Func();
     }
            
     class  A :I 
     {
      public  virtual  void  Func() 
      { 
       Console.WriteLine("FuncA");
      }
     }
           
     class  B  :  A  ,  I    //注意这里的意思?
     {
      public  void  Func()  {  Console.WriteLine("FuncB");}
     }       
           
     class  C  :    A 
     {
      public  override  void  Func()  {  Console.WriteLine("FuncC");}
     }   

     class Class1
     {
      /**//// <summary>
      /// 应用程序的主入口点。
      /// </summary>
      [STAThread]
      static void Main()
      {
       I  a  =  new  A()  ;    //申明了接口a,并马上和一个类的实例发生关系了
       I  b  =  new  B()  ;    //申明了接口b,并马上和一个类的实例发生关系了
       I  c  =  new  C()  ;    //申明了接口c,并马上和一个类的实例发生关系了
       a.Func()  ;              //检查a的实例A,  发现A和接口I捆绑了,所以执行A的函数Func  ,结果:  FuncA
       b.Func()  ;              //检查b的实例B,  发现B和接口I捆绑了,所以执行B的函数Func  ,结果:  FuncB
       c.Func()  ;              //家常c的实例C,发现其没有和接口I捆绑,系统继续找它的父类.  发现A和I捆绑了,他就去找函数A,发现A是虚拟函数,系统又从头来找类的实例C,发现C重载(override)了Func,好了,马上执行该函数.  结果是FuncC;
       Console.ReadLine();
      } 
     }
    }

    Comments

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    Trackbacks

    The trackback URL for this entry is:
    http://scordeity.spaces.live.com/blog/cns!4B57FC7A37CEE7E3!196.trak
    Weblogs that reference this entry
    • None