zoukankan      html  css  js  c++  java
  • 类,抽象类与接口之我所见!

      在学习过程中,抽象类与接口二者的关系已被高手阐述了N遍,但是,仅仅罗列出他们之间的区别是不能够表述清晰的,我看了Anytao和KeithDa两位高手写的文章,他们说的都非常好,让我受益非浅,结合二位前辈的经验和我在项目中的体会,斗胆也谈谈他们的关系和取舍!
     
    定义:
      接口:接口是包含一组虚方法的抽象类型,其中每一种方法都有其名称、参数和返回值。接口方法不能包含任何实现;
      抽象类:抽象类提供多个派生类共享基类的公共定义,它既可以提供抽象方法,也可以提供非抽象方法。抽象类不能实例化,必须通过继承由派生类实现其抽象方法.

    应用与取舍:
        二者的使用要看具体情况,有可能只有其中一种,也可能全部使用效果才好.下面做一个我自己认为能说明问题的例子:
     1 // 定义人的抽象类
     2 abstract class people
     3 {
     4      // 定义成员
     5      protected string _name;
     6  
     7      // 定义姓名属性
     8      public abstract string name
     9      {
    10          get:
    11          set:
    12      }
    13  
    14      // 定义交谈方法
    15      public abstract void talk()
    16  
    17      // 定义移动方法
    18      public abstract void move()
    19  }
    20  
    21  
    22  /////////////////////////////////////////////
    23  
    24  // 定义中国人
    25  abstract class Chinaman:people
    26  {
    27      // 构造函数  
    28      public Chinaman(string strname)
    29      {
    30          _name = strname
    31      }  
    32 
    33     // 实现姓名属性成员
    34      public override string name
    35      {
    36          get
    37           {
    38               return _name;
    39           }
    40          set
    41           {
    42               _name = value;
    43           }
    44      }
    45  
    46      // 实现交谈方法
    47      public override void talk()
    48      {
    49          Response.write("我说的是汉语!");
    50      }
    51  
    52      // 实现移动方法
    53      public override void move()
    54     {
    55           Response.write("我步行移动!");
    56     }
    57  }
    58  
    59  
    60  // 定义美国人
    61  abstract class American:people
    62  {
    63      // 构造函数  
    64      public American(string strname)
    65      {
    66          _name = strname
    67      }  
    68  
    69     // 实现姓名属性成员
    70      public override string name
    71      {
    72          get
    73           {
    74               return _name;
    75           }
    76          set
    77           {
    78               _name = value;
    79           }
    80      }
    81  
    82      // 实现交谈方法
    83      public override void talk()
    84      {
    85          Response.write("我说的是英语!");
    86      }
    87  
    88      // 实现移动方法
    89      public override void move()
    90     {
    91           Response.write("我开车移动!");
    92     }
    93  }
    94 
    95 ....

    如果我们定义的类只有具体的人,那以上代码基本可以实现功能,我们也没必要非要用接口,但是.... ,如果有一天我们还要增加其他的类别,比如说:
     1 // 定义动物的抽象类
     2 abstract class animal
     3 {
     4     // 定义成员
     5     protected string _kind;
     6 
     7     // 定义类型属性
     8     public abstract string kind
     9     {
    10         get:
    11         set:
    12     }
    13 
    14     // 定义交谈方法
    15     public abstract void talk()
    16 
    17     // 定义移动方法
    18     public abstract void move()
    19 }
    20 
    21 
    22 /////////////////////////////////////////////
    23 
    24 // 定义羊
    25 abstract class sheep:animal
    26 {
    27     // 构造函数  
    28     public sheep(string strkind)
    29     {
    30         _kind = strkind
    31     }  
    32 
    33    // 实现类型属性成员
    34     public override string kind
    35     {
    36         get
    37          {
    38              return _kind;
    39          }
    40         set
    41          {
    42              _kind = value;
    43          }
    44     }
    45 
    46     // 实现交谈方法
    47     public override void talk()
    48     {
    49         Response.write("咩咩的叫!");
    50     }
    51 
    52     // 实现移动方法
    53     public override void move()
    54    {
    55          Response.write("四蹄行走!");
    56    }
    57 }
    58 
    59 
    60 // 定义鸡
    61 abstract class chicken:animal
    62 {
    63     // 构造函数  
    64     public chicken(string strkind)
    65     {
    66         _kind = strname
    67     }  
    68 
    69    // 实现类型属性成员
    70     public override string kind
    71     {
    72         get
    73          {
    74              return _kind;
    75          }
    76         set
    77          {
    78              _kind = value;
    79          }
    80     }
    81 
    82     // 实现交谈方法
    83     public override void talk()
    84     {
    85         Response.write("喔喔的叫!");
    86     }
    87 
    88     // 实现移动方法
    89     public override void move()
    90    {
    91          Response.write("两爪行走!");
    92    }
    93 }
    94 
    95 
    96 

        比较两段代码,有没有发现其中有共同的部分,其实两个种类有相同的方法成员,(交谈和移动),我们可以把它提取出来做为接口,让所有具体有该行为的类继承该接口.

         可是,慢着,如果我不提取出来,保持现在这个样子不是很好吗? 现在看起来是没有任何问题,但是如果某一天,系统要求中国人,美国人,鸡,羊都要增加"吃饭" 这个方法呢? 以后还要增加 "喝水" ,"高兴的表情".... 诸如此类,,现在只有两个抽象类还不算太坏,如果还增加其他种类,比如说:我想从动物种类中单独出来 "家畜类","哺乳动物类","鸟类".... 在这种情况下还是用这种单一的抽象类继承是非常棘手的. 这时我们可以将所有类的普遍行为归为一个接口,而将每个种类特有的行为和属性归类到一个抽象类中,这样既保持了具体类既有它的特有行为,也有共同的行为 ,具体时候之后大概会是酱紫:
     1 // 人的抽象类
     2 public abstract class people
     3 {
     4     // 人类特有的行为    
     5     public abstract void 劳动()
     6 }
     7 
     8 // 鸟类的抽象类
     9 public abstract class Aves
    10 {
    11     // 鸟类动物特有的行为
    12     public abstract void 飞翔()
    13 }
    14 
    15 // 公共接口
    16 public interface IAction
    17 {
    18     // 普遍的行为
    19   public void move();
    20     public void talk();
    21 }
    22 
    23 /////////////////////////////////////////
    24 
    25 // 定义中国人
    26 public class Chinaman:people,IAction
    27 {
    28   //  实现抽象类和接口方法
    29 }
    30 
    31 
    32 // 定义麻雀
    33 public class spadger:Aves,IAction
    34 {
    35   //  实现抽象类和接口方法
    36 }
    37 


      经过上面的改造,定义的麻雀和中国人既有自己的特殊方法,也有普遍方法,(有人说把接口定义改成抽象方法,虽然也可以,但是类继承是单一继承的,多继承好象不可以),当然,你也可以扩展你的接口,例如说你可以将 鸟类,猫科动物类共同的行为提取出来,做为一个新的接口.定义一个新类,要他包含接口中定义的所有方法,那么就继承该接口并实现它.

     抽象类和接口在结构比较单一的类集合中区别不是太大,但如果系统复杂,类关系多样,利用二者,相互结合使用,会大大降低系统耦合度,也让整个系统功能更容易扩展,其内部结构也一目了然.
     
        个人认为,抽象类注重小范围的,具有某些共性成员的成员描述,而接口,是对某些成员具有的共同行为的形态描述.它是不限范围的.

  • 相关阅读:
    开发时需要安装的插件
    update svn cache 慢
    eclipse cut copy paste plugin
    eclipse怎么自定义工具栏
    Eclipse Class Decompiler——Java反编译插件(转)
    2014年下半年软考系统架构设计师考试试题
    IT痴汉的工作现状36-做好准备再上路
    JSP简单练习-EL获取表单数据
    !HDU 1078 FatMouse and Cheese-dp-(记忆化搜索)
    iOS百度地图
  • 原文地址:https://www.cnblogs.com/kingcat/p/758323.html
Copyright © 2011-2022 走看看