Effective Java 18:接口优于抽象类 Prefer interfaces to abstract classes

来源:互联网 发布:哈尔滨网络广播直播 编辑:程序博客网 时间:2024/05/21 10:29

Java程序设计语言提供了两种机制,可以用来定义允许多个实现的类型:接口和抽象类

因为Java只允许单继承,所以抽象类作为类型定义受到了极大的限制


———————————————————————————————————————————————


现有的类可以很容易地被更新,以实现新的接口

一般来说,无法更新现有的类来扩展新的抽象类


如果你希望让两个类扩展同一个抽象类,就必须把抽象类放到类型层次(type hierarchy)的最高处

以便这两个类的一个祖先成为它的子类,但这样做会间接地伤害到类层次,迫使这个公共祖先的所有后代类都扩展这个新的抽象类


———————————————————————————————————————————————


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


不严格地讲,mixin是指这样的类型:

类除了实现它的“基本类型之外(primary type)”之外,还可以实现这个mixin类型,以表明它提供了某些可供选择的行为

这样的接口之所以被称为mixin,是因为它允许人选的功能可被混合到类型的主要功能之中


抽象类不能被用于定义mixin,类不可能有一个以上的父类,类层次结构中也没有适当的地方来插入mixin


———————————————————————————————————————————————


接口允许我们构造分层次结构的类型框架


类型层次对于组织某些事物是非常合适的,但是其他有些事物并不能被整齐地组织成一个严格的类型层次

例如我们有一个接口代表一个singer,另一个接口代表一个songwriter

当我们碰到鲍勃迪伦这种神一般的存在的时候,就可以定义第三个接口,它同时扩展了Singer和Songwriter

public interface SingerSongwriter extends Singer,Songwriter

并可以添加一些适用于这种组合的新方法


而另外一种做法是编写一个臃肿的类层次,对于每一种要被支持的属性进行组合,都包含一个单独的类

如果在整个类型系统中有n个属性,那么就必须支持2的n次方种可能的组合

这种现象被称为组合爆炸(combinatorial explosion)

类层次臃肿会导致类也臃肿,这些类包含许多方法,造成不必要的复杂


———————————————————————————————————————————————


通过第16条中介绍的包装类(wrapper class)模式,接口使得安全地增强类的功能成为可能


通过对你导出的每个重要接口都提供一个抽象的骨架实现(skeletal implementation)类,把接口和抽象类的优点结合起来

接口的作用仍然是定义类型,但是骨架实现类接管了所有与接口实现相关的工作

例如,Collections Framework为每个重要的集合接口都提供了一个骨架实现,包括AbstractCollection、AbstractSet、AbstractList和AbstractMap


———————————————————————————————————————————————


抽象类的一个明显的优势:抽象类的演变比接口的演变要容易得多

如果在后续的发行版本中,你希望在抽象类中增加新的方法,始终可以增加具体方法,它包含合理的默认实现

但对于接口,这样做显然是行不通的


设计公有的接口要非常谨慎,接口一旦被公开发行,并且已被广泛实现,再想改变这个接口几乎是不可能的


简而言之,接口通常是定义允许多个实现的类型的最佳途径

这条规则有个例外,即当演变的容易性比灵活性和功能更为重要的时候

0 0
原创粉丝点击