基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

接口与抽象类的核心区别

知识点图片

本文对比了接口和抽象类的区别:接口是定义“能做什么”的行为契约,而抽象类是定义“是什么”的继承模板。

我们来直接、清晰地对比一下接口(Interface)和抽象类(Abstract Class)的核心区别。

一句话核心区别

  • 抽象类 (Abstract Class) 像一个“半成品模板”,它定义了一个物种的共同基因和部分能力,强调 “是什么 (is-a)” 的关系。
  • 接口 (Interface) 像一张“能力资格证”,它只定义了获得该能力需要掌握的技能列表,强调 “能做什么 (can-do)” 的关系。

详细对比表

对比维度 抽象类 (Abstract Class) 接口 (Interface)
设计理念 “是什么” (is-a)
用于代码复用和模板化。子类和抽象类之间是强烈的父子/继承关系。例如, 一种 动物
“能做什么” (can-do / has-a)
用于定义行为规范或契约。实现类之间可能毫无关系。例如,飞机超人 都能
继承/实现 使用 extends 关键字继承。
只能单继承,一个类只能有一个直接父类。
使用 implements 关键字实现。
可以多实现,一个类可以同时实现多个接口。
成员变量 可以有各种成员变量 (public, protected, private, static, final等)。可以包含对象的状态。 只能有 public static final 常量
它不包含对象的状态,只定义常量。
方法 1. 抽象方法:只有声明,没有实现,子类必须重写。
2. 具体方法:有完整实现,子类直接继承使用,提供了代码复用。
1. 抽象方法:(Java 8前) 只有抽象方法,实现类必须全部实现。
2. 默认方法 (Default Method):(Java 8+) 可以提供默认实现,实现类可直接使用或重写。
3. 静态方法 (Static Method):(Java 8+) 属于接口本身,不能被实现类继承或重写。
构造函数 有构造函数,但不能被实例化 (new)。其构造函数主要用于被子类调用 (super()) 来初始化父类部分。 没有构造函数。因为它不是一个类,只是一个行为契约。
访问修饰符 方法可以是 public, protected, private (private方法不能是抽象的)。 方法默认且只能是 public (Java 9+ 允许 private 方法)。

如何选择:一个简单的决策指南

你应该使用抽象类,当...

  1. 你想在多个相关的子类之间共享代码。抽象类可以提供具体方法的实现,这是接口(在有默认方法前)做不到的。
  2. 你希望子类拥有共同的状态(成员变量)和方法。这些子类有很强的“亲缘关系”。
  3. 你想控制方法的访问权限。比如某些方法只允许子类内部使用 (protected)。

场景示例:定义一个 图形 (Shape) 抽象类,它有 颜色 (color) 属性和 计算面积 (calculateArea()) 的抽象方法。圆形 (Circle)矩形 (Rectangle) 继承它,它们都共享 颜色 属性,但各自实现自己的面积计算方式。

你应该使用接口,当...

  1. 你希望定义一个行为规范,让完全不相关的类去实现。例如,Comparable(可比较的)、Serializable(可序列化的)。任何对象都可以实现它们以获得相应能力。
  2. 你想利用多重继承的优势。一个类可以同时是 Flyable(能飞的)和 Swimmable(能游的)。
  3. 你想实现系统的解耦。通过面向接口编程,调用方只关心对象有没有某个能力(接口),而不关心它的具体类型(实现类),这让替换实现变得非常容易。

场景示例:定义一个 警报 (Alarm) 接口,它有 触发警报 (trigger()) 方法。门 (Door)烟雾传感器 (SmokeSensor)App 都可以实现这个接口。它们本质不同,但都能触发警报。

总结

  • 抽象类是关于“继承”的,侧重于代码复用和物种分类。
  • 接口是关于“契约”的,侧重于行为规范和系统解耦。

在现代软件设计中,有一个普遍的原则:“优先使用接口”。因为它能提供更好的灵活性和解耦能力。只有当你需要强制子类继承某些状态和共享代码实现时,才考虑使用抽象类。

00:00
00:00