抽象类和接口职责不同:抽象类用于共享状态与部分实现,体现“is-a”关系;接口用于定义行为契约与能力组合,支持多实现和解耦。二者常混合使用,接口定契约,抽象类简化实现。

抽象类和接口不是可互换的替代品,它们各自有明确的职责边界。选错会导致设计僵化、扩展困难,甚至破坏开闭原则。
抽象类适用:共享状态与部分实现
当多个类属于同一语义层级、有共同字段和可复用逻辑时,抽象类是自然选择。它能封装构造过程、初始化共享状态,并提供默认行为。
- 包含成员变量(如
protected String name)、构造方法、普通方法和抽象方法 - 体现“is-a”关系,比如
Animal抽象类定义了所有动物共有的sleep()实现和必须重写的makeSound() - 适合模板方法模式:抽象类定义骨架流程(如
prepare() → cook() → serve()),子类只定制关键步骤
接口适用:行为契约与能力组合
接口不承载状态,只声明“能做什么”。它让无关类统一遵循同一规范,支持横向能力叠加,是解耦和多态的基础。
- 定义纯行为契约,如
Comparable、Serializable、Runnable,不关心实现类是什么 - 一个类可实现多个接口,例如
class Drone implements Flyable, CameraOperable, RemoteControllable - Java 8+ 的
default方法可用于提供非核心的通用逻辑(如checkMoney()),但不应替代抽象类的主干复用
混合使用:接口定义能力,抽象类简化实现
大型系统中二者常协同工作:先定义接口确立契约,再用抽象类为常见实现提供基础支持。
- 例如,定义
Payment接口后,提供AbstractPayment抽象类实现日志、幂等校验、回调通知等通用逻辑 - 子类只需继承抽象类并实现核心
doPay(),避免重复造轮子,又不强制绑定单一父类 - 这种模式兼顾了接口的松耦合与抽象类的代码复用,是框架设计的常见实践
决策关键:问自己两个问题
不用背规则,现场判断更可靠:
- 这些类是否天然属于同一类型?—— 是,优先考虑抽象类
- 这个功能是否可能被完全不相关的类共同需要?—— 是,必须用接口
- 要不要在不改变继承链的前提下,给类增加新能力?—— 接口是唯一答案










