接口
抽象类和接口的区别
抽象类可以有方法体的方法,但接口没有(Java 8 以前)。
接口中的成员变量隐式为
static final,但抽象类不是的。一个类可以实现多个接口,但只能继承一个抽象类。
// 隐式的abstract
interface Coach {
// 隐式的public
void defend();
void attack();
}接口是隐式抽象的,所以声明时没有必要使用
abstract关键字;接口的每个方法都是隐式抽象的,所以同样不需要使用
abstract关键字;接口中的方法都是隐式
public的。
抽象类是对一种事物的抽象,即对类抽象,继承抽象类的子类和抽象类本身是一种 is-a 的关系。而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。
举个简单的例子,飞机和鸟是不同类的事物,但是它们都有一个共性,就是都会飞。那么在设计的时候,可以将飞机设计为一个类 Airplane,将鸟设计为一个类 Bird,但是不能将 飞行 这个特性也设计为类,因此它只是一个行为特性,并不是对一类事物的抽象描述。
此时可以将 飞行 设计为一个接口 Fly,包含方法 fly(),然后 Airplane 和 Bird 分别根据自己的需要实现 Fly 这个接口。然后至于有不同种类的飞机,比如战斗机、民用飞机等直接继承 Airplane 即可,对于鸟也是类似的,不同种类的鸟直接继承 Bird 类即可。从这里可以看出,继承是一个 "是不是"的关系,而 接口 实现则是 "有没有"的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比如鸟是否能飞(或者是否具备飞行这个特点),能飞行则可以实现这个接口,不能飞行就不实现这个接口。
接口是对类的某种行为的一种抽象,接口和类之间并没有很强的关联关系,举个例子来说,所有的类都可以实现 Serializable 接口,从而具有序列化的功能,但不能说所有的类和 Serializable 之间是 is-a 的关系。
接口定义
注意事项
接口中定义的变量会在编译的时候自动加上
public static final修饰符没有使用
private、default或者static关键字修饰的方法是隐式抽象的,在编译的时候会自动加上public abstract修饰符。也就是说上例中的getElectricityUse()其实是一个抽象方法,没有方法体——这是定义接口的本意。从 Java 8 开始,接口中允许有静态方法
接口中允许定义
default方法也是从 Java 8 开始的,比如说上例中的printDescription()方法,它始终由一个代码块组成,为实现该接口而不覆盖该方法的类提供默认实现。接口不允许直接实例化,需要定义一个类去实现接口,也因此接口不能是 final 的
接口可以是空的。最典型的例子就是 Serializable 接口,在
java.io包下。接口的抽象方法不能是 private、protected 或者 final
接口的作用
使某些实现类具有我们想要的功能,比如说,实现了 Cloneable 接口的类具有拷贝的功能,实现了 Comparable 或者 Comparator 的类具有比较功能。
Cloneable 和 Serializable 一样,都属于标记型接口,它们内部都是空的。实现了 Cloneable 接口的类可以使用 Object.clone() 方法,否则会抛出 CloneNotSupportedException。
Java 原则上只支持单一继承,但通过接口可以实现多重继承的目的
实现多态。多态可以通过继承(extends)的关系实现,也可以通过接口的形式实现父类引用指向子类对象
接口的三种模式
在使用接口的时候,经常会用到三种模式,分别是策略模式、适配器模式和工厂模式。
策略模式
策略模式的思想是,针对一组算法,将每一种算法封装到具有共同接口的实现类中,接口的设计者可以在不影响调用者的情况下对算法做出改变。
Demo.defend() 方法可以接受不同风格的 Coach,并根据所传递的参数对象的不同而产生不同的行为,这被称为“策略模式”
适配器模式
适配器模式的思想是,针对调用者的需求对原有的接口进行转接。生活当中最常见的适配器就是HDMI线,可以同时发送音频和视频信号。适配器模式的示例如下:
Coach 接口中定义了两个方法(defend() 和 attack()),如果类直接实现该接口的话,就需要对两个方法进行实现。
如果我们只需要对其中一个方法进行实现的话,就可以使用一个抽象类作为中间件,即适配器(AdapterCoach),用这个抽象类实现接口,并对抽象类中的方法置空(方法体只有一对花括号),这时候,新类就可以绕过接口,继承抽象类,我们就可以只对需要的方法进行覆盖,而不是接口中的所有方法。
工厂模式
什么工厂生产什么,比如说宝马工厂生产宝马,奔驰工厂生产奔驰,A 级学院毕业 A 级教练,C 级学院毕业 C 级教练。示例如下:
最后更新于