如何在不违反SOLID原则下正确修改子类Knight的attack字段值?
问题解答
首先明确:绝对不要把attack字段改成public。直接暴露私有字段会彻底破坏封装性——后续如果要给attack添加校验逻辑(比如限制攻击值不能为负),你得修改所有直接访问这个字段的代码,完全违反了SOLID中的开闭原则(OCP),也违背了面向对象设计的核心思想。
你的现有代码能实现需求,但确实有更优雅且符合SOLID的优化方案:
更优实现:使用父类参数化构造器
核心思路是让父类Warrior提供带参数的构造器,子类Knight通过调用这个构造器直接初始化正确的属性值,避免先设默认值再修改的冗余操作,同时保留封装性。
优化后的Warrior类
public class Warrior { private int health; private int attack; // 无参构造器,使用默认属性值 public Warrior() { this(50, 5); } // 受保护的参数化构造器,允许子类定制初始属性 protected Warrior(int health, int attack) { this.health = health; // 可在此添加属性校验逻辑,比如攻击值不能为负 if (attack < 0) { throw new IllegalArgumentException("攻击值不能为负数"); } this.attack = attack; } // 提供getter方法供外部访问属性(按需保留) public int getAttack() { return attack; } // 如果攻击值不需要后续修改,建议移除setAttack方法,强化封装 // public void setAttack(int attack) { // this.attack = attack; // } }
优化后的Knight类
public class Knight extends Warrior { public Knight() { // 直接调用父类构造器,传入骑士的专属攻击值7,生命值沿用父类默认的50 super(50, 7); } }
为什么这个方案更符合SOLID?
- 开闭原则(OCP):父类通过参数化构造器开放了定制扩展点,子类无需修改父类内部逻辑就能实现属性定制;后续如果要添加属性校验,只需在父类构造器中修改,不影响所有子类。
- 封装性:字段始终保持
private,不会暴露给外部代码,避免了随意修改属性的风险。 - 代码简洁性:跳过了先初始化默认攻击值再修改的冗余步骤,直接一步到位完成正确初始化。
内容的提问来源于stack exchange,提问作者Fellou98
相关产品推荐
相关产品推荐

