16、接口优于抽象类
作者有一个观点就是
² 接口是定义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的实现
};
That’s all!^_^