抽象类设计应聚焦本质身份(is-a)而非能力(can-do),用接口定义飞行、加密等行为;继承深度不超过两层,优先组合与接口实现;抽象方法约束核心契约,具体方法封装稳定逻辑。

设计抽象类时,关键不是堆叠层级,而是明确职责边界、控制可扩展路径。过度继承往往源于把“共性”和“能力”混为一谈,或过早固化行为假设。
聚焦“是什么”,而非“能做什么”
抽象类应表达本质身份(is-a),比如 Animal、PaymentMethod、DocumentParser;而飞行、游泳、加密、校验等属于能力(can-do),更适合用接口定义。
- 错误做法:在
AbstractBird中直接写fly()方法,迫使鸵鸟、企鹅重写并抛异常 - 正确做法:保留
AbstractBird表达鸟类本质(如有喙、产卵、恒温),把Flyable、Swimable拆成接口,由具体子类按需实现
控制继承深度,通常不超过两层
Java 只支持单继承,但抽象类可以层层继承,容易滑向三层甚至四层(如 Animal → Mammal → Carnivore → Lion)。这种结构一旦需求变动(比如某“Carnivore”突然要吃素),整个链就脆弱。
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 建议:抽象类最多一层直接继承(即子类只继承一个抽象父类),再往上用组合或接口补充行为
- 例如:
Lion继承Mammal,而捕食逻辑通过HuntingStrategy接口注入,不硬编码在继承链中
用抽象方法划定契约,用默认/具体方法提供稳定基础
抽象类的价值在于既约束又赋能——抽象方法强制子类思考“必须做什么”,具体方法则封装“大家都会怎么做的通用逻辑”。
- 把易变、有例外的行为设为抽象方法(如
makeSound()),让子类决定 - 把稳定、复用度高的逻辑写成具体方法(如
logCreationTime()、validateIdFormat()) - 避免在抽象类中塞过多“半成品”方法,尤其那些未来可能被频繁重写的
优先让抽象类实现接口,而不是被多层继承
抽象类本身可以 implements 多个接口,这比拉长继承链更灵活。它既能统一身份,又能组合能力。
- 例如:
abstract class PaymentProcessor implements Retryable, Loggable, Secure - 子类(
AlipayProcessor、CryptoProcessor)只需关注自身实现细节,不必关心“Retryable 是从哪一层继承来的” - 当新能力出现(如支持异步回调),只需新增
AsyncCallback接口,已有抽象类可选择性实现,不影响继承结构
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










