抽象类 —— 一种模板式设计
1 abstract void fun(); 2 [public] abstract class ClassName { 3 abstract void fun(); 4 }
- 抽象类就是为了继承而存在
- 抽象类不能被实例化,实例化 交由它的子类完成,它只需要有一个引用即可。
- 抽象方法必须由子类来进行重写。必须为public或者protected,缺省情况下默认为public
- 只要包含一个抽象方法的抽象类,该方法必须要定义成抽象类,不管是否还包含有其他方法。
- 抽象类中可以包含具体的方法,当然也可以不包含抽象方法。
- abstract不能与final并列修饰同一个类。
- abstract 不能与private、static、final或native并列修饰同一个方法。
- 抽象类的意义在于:
- 为其子类提供一个公共的父类型,避免该类被实例化;
- 封装子类中的重复内容(成员变量和方法);
- 定义公共抽象方法,由子类提供不同的实现。
接口 —— 一种辐射式设计(一种行为规范)
1 [public] interface InterfaceName { 2 3 }
- 接口 本身不是类
- 变量 被隐式地指定为public static final (只能是public static final变量,用private修饰会报编译错误)
- 方法【必须都抽象方法】 被隐式地指定为public abstract (只能是public abstract方法)
- 接口中所有的方法不能有具体的实现
接口是一种极度抽象的类型,比抽象类更加“抽象”,并且一般情况下不在接口中定义变量
对比 ——
语法层面上的区别
1)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
4)一个类只能继承一个抽象类,而一个类却可以实现多个接口。
设计层面上的区别
- 什么是模板式设计?例子:用模板A设计了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A,如果公共部分需要改动,则只需要改动模板A就可以了,不需要重新对ppt B和ppt C进行改动
- 什么是辐射式设计?比如某个电梯都装了某种报警器,一旦要更新报警器,就必须全部更新。
抽象类是自底向上抽象而来的,接口是自顶向下设计出来的
- 对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;
- 而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。
实例 ——
看一个网上流传最广泛的例子:门和警报的例子:门都有open( )和close( )两个动作,此时我们可以定义通过抽象类和接口来定义这个抽象概念:
1 abstract class Door { 2 public abstract void open(); 3 public abstract void close(); 4 }
或者:
1 interface Door { 2 public abstract void open(); 3 public abstract void close(); 4 }
这种方法违反了面向对象设计中的一个核心原则ISP (Interface Segregation Principle)【见批注】,在Door的定义中把Door概念本身固有的行为方法和另外一个概念"报警器"的行为方 法混在了一起。这样引起的一个问题是那些仅仅依赖于Door这个概念的模块会因为"报警器"这个概念的改变而改变,反之依然。
Door的open() 、close()和alarm()根本就属于两个不同范畴内的行为,open()和close()属于门本身固有的行为特性,而alarm()属于延伸的附加行为。因此最好的解决办法是单独将报警设计为一个接口,包含alarm()行为,Door设计为单独的一个抽象类,包含open和close两种行为。再设计一个报警门继承Door类和实现Alarm接口。
1 interface Alram { 2 void alarm(); 3 } 4 5 abstract class Door { 6 void open(); 7 void close(); 8 } 9 10 class AlarmDoor extends Door implements Alarm { 11 void oepn(){ 12 //.... 13 } 14 void close(){ 15 //.... 16 } 17 void alarm(){ 18 //.... 19 } 20 }
批注:
ISP(Interface Segregation Principle接口分离原则):面向对象的一个核心原则。它表明使用多个专门的接口比使用单一的总接口要好。
一个类对另外一个类的依赖性应当是建立在最小的接口上的。
一个接口代表一个角色,不应当将不同的角色都交给一个接口。没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染。