子类扩展父类功能的核心是自然融合、语义清晰、职责分明,需明确边界、守约重写、可靠初始化,并优先组合而非继承。

子类扩展父类功能,核心不是“多写几个方法”,而是让新增行为与原有结构自然融合、语义清晰、职责分明。关键在于理解“扩展”是增强能力,不是堆砌逻辑。
明确扩展边界:只加子类独有的行为
父类定义通用契约,子类只补充它不具备但业务必需的能力。比如 Animal 有 eat() 和 sleep(),Dog 可以加 bark(),Cat 加 meow()——这些方法在 Animal 中没有意义,也不该强行塞进去。
- 新增方法必须有明确的子类语义,不能是“所有动物都可能用到”的模糊功能
- 避免在子类里重复实现父类已有的逻辑(如再写一遍 eat 的具体流程)
- 如果多个子类都要加相似功能(比如“奔跑”),考虑提取为新抽象层(如 Runnable 接口),而不是各自硬编码
重写要守约:修改行为,不破坏契约
重写父类方法(@Override)是为了适配子类特性,但必须保持调用方预期不变。比如 Animal 的 move() 表示“改变位置”,Dog 的 move() 可以是“四脚奔跑”,Fish 的 move() 是“摆尾游动”,但都不能让它突然打印日志或抛出无关异常。
- 方法签名(参数类型、返回值、异常声明)必须完全一致
- 输入范围、输出含义、副作用(如是否修改状态)应与父类文档约定一致
- 若父类方法声明为 final,说明设计者已判定不可扩展,此时应另寻组合或委托方式
善用构造与初始化:子类状态要独立可靠
子类实例化时,既要正确初始化父类部分(通过 super() 调用),也要完成自身特有字段的设置。比如 Dog 除了 name 和 age,还有 breed 字段,就必须在构造器中一并处理。
- super() 必须是子类构造器第一句(显式或隐式),确保父类状态先就绪
- 子类自己的字段不要依赖父类未初始化的中间状态
- 避免在构造过程中调用可被重写的方法(可能导致子类逻辑在父类尚未构造完成时执行)
优先组合而非继承:当扩展变复杂时
如果子类需要大量新增功能,且这些功能与父类语义关联弱(比如给 Dog 加 GPS 定位、语音识别、健康监测),说明它正在偏离“动物”本质。这时更适合把功能拆成独立组件,通过字段持有并委托调用。
- 例如:Dog 持有 Tracker tracker 和 HealthMonitor monitor,而不是把所有方法塞进 Dog 类
- 组合更灵活,易于测试、替换和复用;继承更适合表达“是一种”的强关系(Dog is-a Animal)
- Java 不支持多重继承,但接口 + 组合能自然支持多种能力叠加
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











