0%

Java 接口与抽象类

简介

接口与抽象类是面向对象思想的两个重要概念, 接口仅定义方法签名和常量值, 抽象类可定义普通类所包含的所有内容, 还可定义抽象方法, 接口, 抽象类本身不能示例化, 必须在相应子类中实现抽象方法

抽象类

如果一个类含有抽象方法, 则称这个类为抽象类, 抽象类必须在类前用 abstract 关键字修饰, 抽象方法是一种只有声明, 而没有具体的实现的方法

抽象类和普通类区别

  • 抽象方法必须为 public 或者 protected (因为如果为 private, 则不能被子类继承, 子类便无法实现该方法) , 缺省情况下默认为public
  • 抽象类不能用来创建对象
  • 如果一个类继承于一个抽象类, 则子类必须实现父类的抽象方法, 如果子类没有实现父类的抽象方法, 则必须将子类也定义为 abstract 类

接口

接口可以包含抽像方法和静态常量, 均为 public

变量会被隐式地指定为 public static final 变量 (并且只能是 public static final 变量, 用 private 修饰会报编译错误) , 而方法会被隐式地指定为 public abstract 方法且只能是 public abstract 方法 (用其他关键字, 比如 private, protected, static, final 等修饰会报编译错误)

抽象类与接口区别

  • 一个类只能继承一个抽象类, 但是可以实现多个接口
  • 抽象类可以包含类变量, 成员变量, 可以包含非抽象方法, 接口只能包含不可更改的类变量和抽象方法
  • 接口中定义的变量默认都是 public static final 型, 且必须给其初值, 所以实现类中不能重新定义, 也不能改变其值
  • 接口中不能有静态方法, 静态方法是类方法, 不允许子类覆写的, 抽象类可以包含静态方法

抽象的思考

  • 抽象类是对类抽象, 而接口是对行为的抽象, 抽象类是对整个类整体进行抽象, 包括属性, 行为, 但是接口却是对类局部 (行为) 进行抽象
  • 抽象类和派生类之间必须存在 “is-a” 关系, 即父类和派生类在概念本质上应该是相同的, 接口和实现类则存在着 “like-a” 关系, 仅仅是实现了接口定义的契约而已
  • 抽象类是归纳出所有子类的相同点, 设计特点是由多个子类重构而成, 接口是定义了规范, 并由所有子类进行实现

实例

面向对象的一个核心原则 ISP (Interface Segregation Principle) : 使用多个专门的接口比使用单一的总接口要好, 一个类对另外一个类的依赖性应当是建立在最小的接口上的, 一个接口代表一个角色, 不应当将不同的角色都交给一个接口, 没有关系的接口合并在一起, 形成一个臃肿的大接口, 这是对角色和接口的污染

所以不能无限制的往抽象类或者某个接口上面添加方法, 这样必然会导致一个臃肿的接口

下面的例子通过一个带有警报功能的门进行了描述, 它是作为普通门的一份子, 同时它也属于一类警报类工具, 这样即定义了 带有警报功能的门 is a 门, 同时带有警报功能的门 like a 警报工具

之所以将门作为一个抽象类, 是因为所有的门都拥有统一的属性, 例如把手, 拥有统一的功能, 例如开关, 具体的材质, 类型由特定的门进行实现即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 定义了一个大众的门, 具有门的功能, 需要实现每个门的材质类型
abstract class Door{
abstract void type();
void open(){}
void close(){}
}
// 定义警报接口
interface Alarm{
void alarm();
}
// 实现一个具有警报功能的门
class AlarmDoor extends Door implements Alarm{
void type(){}
void alarm(){}
}

参考