第18条:接口优于抽象类
Java提供两种机制,可以用来定义允许多个实现的类型:接口和抽象类。
接口的优势:
1.现有的类可以很容易被更新,以实现新的接口。 只需要给类增加必要的方法,只需在声明中增加一个implements子句。
2.接口是定义混合类型的理想选择。 混合类型(mixin)指类除了实现“基本类型(primary type)”之外,还可以实现这个混合类型,以表明它提供了某些可供选择的行为,例如Comparable是一个接口,它表明允许它的实例与其他可相互比较的对象进行排序。抽象类不可以定义混合类型,因为类不可能有一个以上的父类。
3.接口允许构造非层次结构的类型框架。 类型层次对组织某些事物非常合适,但有些事物不可能被整齐地组织成一个严格的层次结构,假如有两个接口,singer和songwriter:
public interface Singer {
AudioClip sing(Song s);
}
public interface Songwriter {
Song compose(boolean hit);
}
实际上,我们可以定义第三个接口,它本身是singer同时也是个songwriter,同时扩展Singer和Songwriter,并添加一些适合于这种组合的新方法 :
public interface SingerSongwriter extends Singer, Songwriter {
AudioClip strum();
void actSensitive();
}
通过导出的每个重要接口都提供一个抽象的骨架实现类,把接口和抽象类的优点结合起来。
集合的所有接口 都有自己的骨架实现类,所以定义重要接口的时候 最好也定义骨架类来完成通用方法的实现。
抽象类的特点:
抽象类比接口容易演变,接口一旦定义,如果修改,会影响所有实现他的类。
而抽象类 扩展一个方法后 再定义一个合理的默认实现,就不会影响继承他的类。
即使接口和他的骨架类 同时更新了方法,依然还会有漏洞,因为可能会有部分类直接实现接口而没有通过骨架类。
所以定义接口一定要考虑完善 完成后就不要轻易修改,可以扩展子接口的方式。
interface A{
String get();
void set(String a);
}
abstract class B implements A{
@Override
public String get() {
return null;
}
}
class C implements A{
@Override
public String get() {
return null;
}
@Override
public void set(String a) {
System.out.println("324");
}
public String setA(){
return new D().get();
}
class D extends B{
@Override
public void set(String a) {
System.out.println("5345");
}
}
//该方法时 静态工厂 利用B骨架类生产A的匿名实例(使用结束就销毁)。同时也是多重继承的一种方式。
static A getA(final String s){
if (s == null ){
throw new NullPointerException();
}
return new B() {
public String get(String string) {
return s.replaceAll("-","") ;
}
@Override
public void set(String a) {
System.out.println(s);
}
public int size(){
return s.length();
}
};
}
}