整洁编码实践:父类调用子类属性的实现方案优化咨询
方案合理性分析
- 方案1(DocA实现)不合理:子类重复声明
path属性会造成属性隐藏,父类和子类会各自持有一个同名的path变量,极易出现取值不一致的隐性BUG,冗余定义属性也提高了后续维护成本。 - 方案2(DocB实现)不合理:父类的
getPathB仅做参数透传,没有任何公共逻辑价值,子类还需要额外封装一层调用,属于无效封装,也不支持后续公共逻辑的统一迭代。
更优实现方案
推荐用「父类统一收归公共逻辑+子类通过构造器传参/实现抽象方法」的模式,根据属性是否固定可选两种写法:
方案1:固定属性走构造器传参(最简洁,适合属性值固定的场景)
父类统一定义公共属性和公共方法,强制子类构造时传入自身的专属属性值,无需子类重复声明属性:
// 父类抽象类 abstract class Document { // 父类统一持有公共属性,用final避免被意外修改 private final String path; // 父类构造器强制子类必须传入path值 protected Document(String path) { this.path = path; } // 公共逻辑统一在父类实现,后续修改只要改这里,所有子类自动生效 public void printPath() { System.out.println("文档路径:" + path); } public String getPath() { return path; } } // 子类实现 class DocumentA extends Document{ public DocumentA () { // 子类仅需要传入自身的专属值即可,无冗余代码 super("pathA"); } } class DocumentB extends Document{ public DocumentB () { super("pathB"); } }
方案2:动态属性走抽象方法(更灵活,适合属性需要动态计算的场景)
如果子类的属性值需要动态生成、不是固定值,可以把属性获取定义为抽象方法,父类公共方法直接调用抽象方法取值:
abstract class Document { // 抽象方法要求所有子类必须实现,返回对应属性值 public abstract String getPath(); // 公共方法统一实现 public void printPath() { System.out.println("文档路径:" + getPath()); } } class DocumentA extends Document{ @Override public String getPath() { // 支持自定义动态逻辑 return "pathA_" + System.currentTimeMillis(); } } class DocumentB extends Document{ @Override public String getPath() { return "pathB"; } }
以上两种写法都符合开闭原则,公共逻辑统一维护,子类代码无冗余,没有无效封装和隐性风险。
内容的提问来源于stack exchange,提问作者Sascha Steger
相关产品推荐
相关产品推荐

