应优先组合而非继承,按语义边界分层设计继承体系,仅在存在清晰“is-a”关系时使用继承;横向能力通过独立接口及default方法实现;父类避免越界逻辑,差异化行为交由子类实现或策略对象注入。

关键在于控制继承的深度和广度,把“复用”和“建模”分开处理——不是所有共性都该塞进继承链,也不是所有子类都必须挂在同一个父类下面。
按语义边界切分继承层级
只在真正存在清晰“is-a”关系时才用继承。比如 Animal → Mammal → Dog 是合理的,但若想给 Dog 加日志、序列化、缓存能力,就不该让 Dog 去继承 Loggable 或 Cacheable 类。
- 顶层抽象类聚焦核心领域概念(如生命体征、运动方式)
- 中层按生物学/业务维度收敛(哺乳、飞行、水生),每层只封装一类变化
- 底层实现类专注具体行为,不承担跨维度逻辑(比如不在 Mammal 里写数据库操作)
用接口替代横向能力继承
多个不相关类需要相同功能(如打印、校验、审计),定义接口并提供 default 方法,比拉出一个通用父类更安全。
- Loggable、Validatable、Auditable 等接口各自独立,类可自由组合实现
- default 方法封装通用逻辑,避免重复代码,又不污染继承体系
- 接口之间无继承关系,不会导致树状结构横向膨胀
优先组合,限制继承链长度
当子类只是为了复用某部分能力而继承(比如 Car 继承 Vehicle 再继承 Device),实际只是“has-a”,就该拆掉继承,改用持有对象的方式。
立即学习“Java免费学习笔记(深入)”;
- 把引擎、制动、导航等能力抽成独立组件类
- Car 类通过字段持有 Engine 实例,构造时注入,运行时可替换
- 避免在 Vehicle 层加 if (type == Electric) 分支,也省去冗余的空方法占位
禁用父类越界逻辑
父类不该为子类特例预留钩子或条件分支。一旦发现父类方法里频繁出现 instanceof 或 type 字段判断,说明继承设计已失衡。
- 把差异化行为上提到抽象方法,由子类各自实现
- 把可配置行为转为策略对象,通过组合注入,而非继承覆盖
- 删除父类中与多数子类无关的字段和方法,宁可多几个小抽象类,也不堆一个大基类


















