Java继承场景下固定值枚举属性是否需要保留在父类中?
方案分析与最优实现
现有三个方案的问题
- 方案1:核心缺陷是没有封住
setBrand的修改入口,业务约束完全没有强制保障,后续很容易出现误修改导致的bug。 - 方案2:父类移除
brand属性后丢失了统一访问入口,使用多态(比如List<Car>遍历)时无法直接获取品牌属性,等于完全浪费了继承的价值。 - 方案3:放弃继承后无法使用多态特性,所有涉及两类车型的统一处理逻辑都要写两遍,可维护性极差。
推荐最优实现
优先采用抽象父类定义统一访问入口、子类各自实现品牌逻辑的方案,既满足业务约束,又保留完整的多态能力:
第一步:改造父类为抽象类
将公共属性(车牌)放在父类,品牌属性不做成员变量定义,只提供抽象getBrand()方法作为统一访问入口:
enum Brand { FORD, FERRARI, TESLA, RENAULT; } public abstract class Car { private String plate; public String getPlate() { return plate; } public void setPlate(String plate) { this.plate = plate; } // 抽象方法,子类各自实现品牌返回逻辑 public abstract Brand getBrand(); }
第二步:实现两个子类
- 燃油车正常定义可变的
brand成员变量,提供get/set方法 - 电动车直接固定返回TESLA,不提供任何修改入口,连多余的成员变量都不需要定义
// 燃油车子类 public class CombustionCar extends Car { private Brand brand; public CombustionCar(Brand brand, String plate) { setPlate(plate); this.brand = brand; } @Override public Brand getBrand() { return brand; } public void setBrand(Brand brand) { this.brand = brand; } } // 电动车子类 public class ElectricCar extends Car { public ElectricCar(String plate) { setPlate(plate); } @Override public Brand getBrand() { // 固定返回TESLA,无任何修改路径 return Brand.TESLA; } }
方案优势
- 完全满足业务约束:电动车品牌没有任何修改入口,从语法层面强制保障了规则
- 保留完整多态能力:可以直接用
List<Car>统一存储两类车型,遍历调用getBrand()就能拿到正确的品牌,不需要做额外的类型判断 - 扩展性好:后续新增其他车型(比如混动车)只需要继承
Car实现getBrand()即可,不需要修改原有父类逻辑 - 无冗余代码:公共属性和方法都放在父类,子类只需要实现差异化逻辑
低改造成本备选方案
如果原有代码大量依赖父类的brand成员变量,改造抽象类成本太高,可以在方案1的基础上重写setBrand()方法兜底:
public class ElectricCar extends Car { public ElectricCar(String plate) { super(Brand.TESLA, plate); } @Override public void setBrand(Brand brand) { // 要么抛出异常明确提示不可修改,要么空实现忽略修改操作 throw new UnsupportedOperationException("电动车品牌固定为TESLA,不允许修改"); } }
内容的提问来源于stack exchange,提问作者rubengonzalez96
相关产品推荐
相关产品推荐

