Java继承应基于真实稳定的“is-a”关系,用abstract class定义抽象骨架与契约,优先组合而非滥用继承,配合@Override和protected精细控制扩展点。

在 Java 中,继承是实现代码复用和建模“is-a”关系的核心机制。它让子类自然获得父类的属性与行为,同时支持按领域语义分层抽象——比如 “Dog is-a Animal”,而非生硬拼凑功能。关键不在于“能不能继承”,而在于“该不该继承”以及“如何继承得干净、可维护”。
明确继承的前提:真实、稳定、单向的“is-a”关系
继承应反映领域中本质的分类关系,而非临时的功能借用。错误示例如下:
- 把
Printer设为Computer的子类(打印机不是一种计算机) - 让
Student继承ArrayList<string></string>(学生不是列表,这是典型的“has-a”误用)
正确做法是聚焦业务语义:
Employee ← Manager、Engineer;
Shape ← Circle、Rectangle;
PaymentMethod ← CreditCard、PayPal。
这些关系在需求变更中相对稳定,且子类确实共享父类的核心身份与契约。
用 abstract class 定义可复用的骨架与强制契约
当父类本身不具独立实例意义(如不能直接 new Shape()),且需提供部分通用实现时,用 abstract class 最合适:
- 声明
abstract方法定义子类必须实现的行为(如double area()) - 提供
final或普通方法封装共用逻辑(如日志记录、参数校验、模板流程) - 定义受保护字段供子类安全访问(如
protected String name;)
示例:
立即学习“Java免费学习笔记(深入)”;
abstract class Vehicle {
protected final String brand;
protected int speed;
protected Vehicle(String brand) { this.brand = brand; }
public final void start() { System.out.println(brand + " started."); }
public abstract void accelerate(); // 子类决定如何加速
}
class Car extends Vehicle {
public Car(String brand) { super(brand); }
public void accelerate() { this.speed += 20; }
}
避免继承滥用:优先组合,谨慎扩展
Java 不支持多继承,过度依赖继承易导致类层次僵化。以下情况应改用组合或接口:
- 需要复用多个来源的行为 → 用接口(
implements Flyable, Swimmable) - 父类职责频繁变动 → 将共用逻辑提取为独立工具类或服务类,通过字段持有(
private Validator validator;) - 子类只重写一两个方法,其余全部调用
super.xxx()→ 可能违反里氏替换原则,考虑策略模式替代
继承应服务于语义清晰性,而非单纯减少代码行数。
配合 @Override 与 protected 精细控制可扩展点
子类扩展父类行为时,显式使用 @Override 不仅增强可读性,还能在编译期捕获签名错误。对可被子类定制的成员,用 protected 替代 public 或 private:
-
protected字段/方法:子类可直接访问,但包外不可见,兼顾复用与封装 - 避免
public非 final 方法暴露内部细节(易被误用或破坏不变量) - 若某方法逻辑固定,加
final修饰,防止子类意外覆盖核心流程
例如:protected void validateInput() 允许子类定制校验规则,而 public final void process() 保证主流程不被绕过。


















