- 接口和内部类为我们提供了一种将接口与实现分离的更加结构化的方法
- 抽象类是普通的类与接口之间的一种中庸之道
9.1 抽象类和抽象方法
- 通用接口建立起一种基本形式,以此表示所有导出类的共同部分,称为抽象类
- Java提供一个叫做抽象方法的机制,这种方法是不完善的,仅有声明没有方法体
abstract void f();
- 包含抽象方法的类叫做抽象类。如果一个类包含一个或多个抽象方法,该类必须被限定为抽象的。(否则,编译器机就会报错)
- 如果有一个类,让其包含任何abstract方法都显得没有实际意义,而且我们想阻止产生这个类的任何对象,那么这时这样做就很有用了
- 使某个类成为抽象类并不需要所有的方法都是抽象的,仅需将某些方法声明为抽象的即可
- 创建抽象类和抽象方法非常有用,因为它们可以使类的抽象性明确起来,并告诉用户呵呵编译器打算怎样拉力使用它们。抽象类还是很重要的重构工具,因为你它们使得我们可以很容易地将公共方法沿着继承层次结构向上移动
9.2 接口
- interface关键字使抽象的概念更向前迈进了一步,它产生一个完全抽象的类,它根本就没有提供任何具体实现
- 接口允许创建者确定方法名,参数列表和返回类型,但是没有任何方法体
- 要想创建一个接口,需要用interface关键字来替代class关键字。可以在interface关键字前面添加public关键字。默认只有包访问权限
- 要让一个类遵循某个特定接口(或者一组接口),需要使用implements关键字
interface Instrament{
void play(Note n);
void adjust();
}
class Wind implements Instrument{
public play(Note n){
System.out.println(n);
}
public adjust(){
System.out.println("我被执行了");
}
}
- 在接口中没有任何方法被声明为时public的,但是它们自动都是public的
9.3 完全解耦
- 只要一个方法操作的是类而非接口,那么你就只能使用这个类及其子类。接口可以很大程度上放宽这种限制
- 创建一个能够根据所传递的参数对象的不同而具有不同行为的方法,被称为策略设计模式
- 你经常碰到的情况是你无法修改你想要使用的类。在这些情况下,可以使用适配器设计模式。适配器中的代码将接受你所拥有的接口,并产生你所需要的接口
- 将接口从具体实现中解耦使得接口可以应用于多种不同的具体实现,因此代码也就更具可复用性
9.4 Java中的多重继承
- 在导出类中,不强制要求必须有一个是抽象的或“具体的”(没有任何抽象方法的)基类。如果要从一个非接口的类继承,那么只能从一个类去继承。其余的基元素都必须是接口。需要将所有的接口名都置于implements关键字之后,用逗号将它们一一隔开
- 将一个具体类和多个接口组合到一起时,这个具体类必须放在前面,后面跟着的才是接口(否则编译器会报错)
- 使用接口的核心原因:为了能够向上转型为多个基类型(以及由此而带来的灵活性),第二个原因是:防止客户端程序员创建该类的对象
- 如果知道某事物应该成为一个基类,那么第一选择应该是使它成为一个接口
9.5 通过继承来扩展接口
- 通过接口,可以很容易地在接口中添加新的方法声明,还可以通过继承在新接口组合数个接口
- 一般情况下,只可以将extends用于单一类,但是可以引用多个基类接口,只需要用逗号将接口名意义分隔开即可
- 组合接口时的名字冲突
a. 当发生类型冲突时,会出现类型不相容的错误信息
b. 在打算组合的不同接口中使用相同的方法名通常会咋成代码可读性的混乱,请尽量避免这种情况
9.6 适配接口
- 接口最吸引人的原因之一就是允许同一个接口具有多个不同的具体实现
- 你主要就是声明:“你可以用任何你想要的对象来调用我的方法,只要我的对象遵循我的接口”
- 如果你创建了一个新的类,并且向让Scanner可以作用于它,那么你就应该让它实现Readable接口
- 我们可以在任何现有类之上添加新的接口,所以这意味着让方法接受接口类型,是一种让任何类都可以对该方法进行适配的方式
9.7 接口中的域
- 因为你放入接口中的任何域都自动是static和final的,所以接口即成为一种很便捷的用来创建常量组的工具。在Java SE5之前使用,现在使用enum
- 初始化接口中的域
a. 在接口中定义的域不能是“空final”,但是可以被非常量表达式初始化
b. 既然域是static的,他们就可以在类第一次被加载时初始化,这发生在任何域首次被访问时
c. 当然,这些域都不是接口的一部分,他们的值被存储在该接口的静态存储区域内
9.8 嵌套接口
- 接口可以嵌套在类或其他接口中
- 在类中嵌套接口的语法是相当显而易见的,就像非嵌套接口一样,可以拥有public和“包访问‘两种可视性
- 嵌套在另一个接口中的接口自动就是public的,而不能声明为private的
9.9 接口与工厂
- 接口是实现多重继承的途径,而生成遵循某个接口的对象的典型方式就是工厂方法设计模式。
- 这与直接调用构造器不同,我们在工厂对象上调用的是创建方法,而该工厂对象将生成接口与某个实现的对象。
- 理论上,通过这种方式,我们的代码将完全与接口的实现分离,这就使得我们可以透明地将某个实现替换为另外一个实现
9.10 总结
- 确定接口是理想选择,因而应该总是选择接口而不是具体的类----这其实是一种引诱
- 恰当的设计原则应该是优先选择类而不是接口。从类开始,如果接口的必需性变得非常明确,那么就进行重构。接口是一种重要的工具,但是他们容易被滥用