抽象类和接口的对比

抽象类 —— 一种模板式设计

1 abstract void fun();
2 [public] abstract class ClassName {
3     abstract void fun();
4 }
  • 抽象类就是为了继承而存在
  1. 抽象类不能被实例化,实例化 交由它的子类完成,它只需要有一个引用即可。
  2. 抽象方法必须由子类来进行重写。必须为public或者protected,缺省情况下默认为public
  3. 只要包含一个抽象方法的抽象类,该方法必须要定义成抽象类,不管是否还包含有其他方法。
  4. 抽象类中可以包含具体的方法,当然也可以不包含抽象方法。
  5. abstract不能与final并列修饰同一个类。
  6. abstract 不能与privatestaticfinalnative并列修饰同一个方法。
  • 抽象类的意义在于:
  1. 为其子类提供一个公共的父类型,避免该类被实例化;
  2. 封装子类中的重复内容(成员变量和方法);
  3. 定义公共抽象方法,由子类提供不同的实现。

接口 —— 一种辐射式设计(一种行为规范)

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)一个类只能继承一个抽象类,而一个类却可以实现多个接口。

设计层面上的区别

  1. 什么是模板式设计?例子:用模板A设计了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A,如果公共部分需要改动,则只需要改动模板A就可以了,不需要重新对ppt B和ppt C进行改动
  2. 什么是辐射式设计?比如某个电梯都装了某种报警器,一旦要更新报警器,就必须全部更新。

抽象类是自底向上抽象而来的,接口是自顶向下设计出来的 

  • 对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;
  • 而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。

 

实例 —— 

看一个网上流传最广泛的例子:门和警报的例子:门都有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接口分离原则):面向对象的一个核心原则。它表明使用多个专门的接口比使用单一的总接口要好。

       一个类对另外一个类的依赖性应当是建立在最小的接口上的。

       一个接口代表一个角色,不应当将不同的角色都交给一个接口。没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染。

 

posted @ 2017-09-23 18:32  EricSUID  阅读(187)  评论(0编辑  收藏  举报