zoukankan      html  css  js  c++  java
  • Java骨架类

    16、接口优于抽象类

    通过对Java源码的学习我们会发现,AbstractCollection实现了Collection接口,List接口继承自Collection接口,AbstractList又继承了AbstractCollection类,并且实现了List接口。

    诸如此种的还有AbstarctSet,AbstarctList,AbstarctMap,都是继承了一个抽象类,又实现了一个上层接口,对此感到不解。

             后来在effective Java上看到,这样做的好处:痛过对你导出的每个重要接口都提供一个抽象的骨架实现类(skeletal implementation)类,把接口和抽象类的优点结合起来。接口的作用仍然是定义类型,但是骨架实现类接管了所有与接口实现相关的工作。

    我对于骨架类的理解是:使得具体子类只专注于自身的特定方法实现,忽略自身不会提供的方法(对于自身的冗余方法).简单说就是没必要一个个实现接口的所有方法,要调用就调用骨架类的.而这里ArrayList不允许忽略任何list接口的方法,必须自己去小心实现每个方法.当有某类只继承abstractlist,那就方便了,只要改写需要改写的部分.

    作者有一个观点就是

    ²        接口是定义mixin(混合类型)的理想选择。

    mixin的定义:一个类除了实现它的基本类型”primitive type”之外,还可以实现这个mixin类型,以表明它提供可供选择的行为,也就是说它允许将可选的功能混合到一个类的基本功能中。

    作者举例Comparable就是一个mixin接口,这个接口提供的可选功能就是它的实例可以与其他的可相互比较的对象进行排序操作。

    基于上面这一点,接口使得我们能够构造出非层次结构的类型框架。

    什么是层次结构框架(class hierarchy)?

    例如:Shapeß------Rectangleß----------Square这样一路继承下来,就是一个继承体系。

    现在如果Shape假设并没有提供可比较的基本功能,而我们要在Square中实现可比较的功能,我们就可以在Square那加入一个旁支Comparable接口,让Square去实现它即可。

    Shapeß------Rectangleß----------Square ß----Square’s sub class

                                                     |

                         Comparableß------

    上面蓝色部分就是一个class hierarchy,而Comparble恰恰就在这个class hierarchy上建立了一个非层次化的结构。

    注:abstract class不能用来定义mixin,因为java不提供class的多重继承机制。

    ²        abstract skeletal implementation class(抽象骨架实现类型)--结合抽象类和接口的优点,java中模拟多重继承

    Interface缺点是无法拥有方法的实现。而抽象骨架实现的优点在于为抽象类提供实现上的帮助,也避免了抽象类作为类型定义时所特有的限制。

    public abstract class AbstractMapEntry implements Map.Entry {
      // Primitives
      public abstract Object getKey();
      public abstract Object getValue();
      //  ...
      // Implements the general contract of Map.Entry.equals
      public boolean equals(Object o) {
        if (o == this) return true;
        if (!o instanceOf Map.Entry))
          return false;
        Map.Entry arg = (Map.Entry) o;
        
        return eq(getKey(), arg.getKey()) &&
            eq(getValue(), arg.getValue());
      }
      
      // Since Object equals was overriden, we better override hashCode!
      public int hashCode() {
        return
          (getKey() == null ? 0: getKey().hashCode()) ^
          (getValue() == null ? 0: getValue().hashCode());
      }
    }
    
    

    书中提示:抽象骨架类专为继承而设计,所以要有详细的文档说明。

    ²        抽象类的演化比接口的演化容易

    我们举例说明这一点吧

    Considering the following code:

    //未演化前的代码:
    
    public abstract class AbrBase{
    
             public void a();
    
             public void b();
    
    };
    
    
    
    public class Sub1 extends AbrBase{
    
             public void a(){
    
             }
    
             public void b(){
    
             }
    
    };
    
    
    
    public interface IBase{
    
             public void c();
    
             public void d();
    
    };
    
    
    
    public class Sub2 implements IBase{
    
             public void c(){
    
             }
    
             public void d(){
    
             }
    
    };
    
    
    
    //进化后代码
    
    public abstract class AbrBase{
    
             public void a();
    
             public void b();
    
    public void e(){// 为抽象类添加一新的具体的方法,注意抽象方法也不行
    
    }
    
    };
    
    
    
    public class Sub1 extends AbrBase{//在抽象类添加一具体方法后,子类可以不用改动
    
             public void a(){
    
             }
    
             public void b(){
    
             }
    
    };
    
    
    
    public interface IBase{
    
             public void c();
    
             public void d();
    
    public void f(); //为接口添加一新的方法
    
    };
    
    
    
    public class Sub2 implements IBase{
    
             public void c(){
    
             }
    
             public void d(){
    
             }
    
             public void f(){ //子类必须修改实现新添加的方法,否则编译将不能通过
    
             }
    
    };
    
    
    
    

    解决办法:提供抽象骨架类
     

    
    //进化之前代码
    
    public interface IBase{
    
             public void c();
    
             public void d();
    
    };
    
    
    
    public abstract class AbrBase implements IBase{
    
             //primitives
    
             public void a();
    
             public void b();
    
    
    
             //implenments the method of IBase interface
    
             public void c(){
    
             }
    
             public void d(){
    
             }
    
    };
    
    
    
    public class Sub extends AbrBase{
    
             public void a(){
    
             }
    
             public void b(){
    
             }
    
    //继承AbrBase对IBase的实现
    
    };
    
    
    
    进化后代码:
    
    public interface IBase{
    
             public void c();
    
             public void d();
    
    public void f(); //为接口添加一新的方法
    
    };
    
    
    
    public abstract class AbrBase implements IBase{
    
             //primitives
    
             public void a();
    
             public void b();
    
    
    
             //implenments the method of IBase interface
    
             public void c(){
    
             }
    
             public void d(){
    
             }
    
             public void f(){ //修改AbrBase以实现IBase新增加的method
    
             }
    
    };
    
    public class Sub extends AbrBase{//无需改变,继承超类对f()方法的实现
    
             public void a(){
    
             }
    
             public void b(){
    
             }
    
    //继承AbrBase对IBase的实现
    
    };
    
    
  • 相关阅读:
    cf536c——思路题
    cf536b——优先队列的运用
    王道论坛和九度论坛
    Ubuntu 12.04 LTS 下配置 apache支持SPDY, 使用wireshark 抓包分析SPDY 协议
    vnc/route/ifconfig 配置
    MIME protocol 说明
    理解邮件传输协议(SMTP、POP3、IMAP、MIME)
    GNU C中的零长度数组
    ftp protocol
    HTTP协议头部与Keep-Alive模式详解
  • 原文地址:https://www.cnblogs.com/cx2016/p/12926151.html
Copyright © 2011-2022 走看看