Java继承中能否重写父类变量名称而非变量值?
嘿,这个问题挺典型的!你现在的代码里,子类Sub1的A1和父类Base的A是完全独立的两个字段——父类的doSomething()只会读取自己定义的A变量,所以直接调用的话肯定打印不出"1"。不过有几种靠谱的方式能实现你想要的效果,我给你逐一拆解:
方案1:用可重写的Getter方法(最优雅的方式)
核心思路是把父类中要打印的字段逻辑抽象成一个方法,让子类重写这个方法来返回自己的变量值,这其实是模板方法模式的简单应用:
先修改父类,把字段封装起来,并提供一个可重写的方法:
public class Base { // 把A改成私有,遵循封装原则 private String A; public String doSomething() { System.out.println(getValueToPrint()); return A; } // 子类可以重写这个方法,返回自己的变量 protected String getValueToPrint() { return A; } }
然后在Sub1里重写这个方法,返回自己的A1:
public class Sub1 extends Base { public String A1; public void setA1(String A1) { this.A1 = A1; } @Override protected String getValueToPrint() { return A1; // 让父类方法用子类的A1变量 } }
这样调用s.doSomething()时,父类的方法会调用子类重写的getValueToPrint(),自然就打印出"1"了。这种方式的好处是父类的逻辑不用改,子类可以灵活替换要使用的变量,扩展性很强。
方案2:直接重写doSomething()方法
如果你的场景比较简单,不想加额外的Getter方法,直接在子类里重写父类的doSomething()也是可行的:
public class Sub1 extends Base { public String A1; public void setA1(String A1) { this.A1 = A1; } @Override public String doSomething() { System.out.println(A1); // 直接打印子类的A1 return A1; // 或者按父类逻辑返回,根据你的需求调整 } }
这种方式更直接,但如果有多个子类都需要修改打印逻辑,会产生重复代码,适合简单场景。
方案3:同步子类变量到父类字段
如果不想修改父类的方法,也可以在子类的setA1方法里,把值同步给父类的A字段:
public class Sub1 extends Base { public String A1; public void setA1(String A1) { this.A1 = A1; super.A = A1; // 将父类的A也设置为A1的值 } }
这样父类的doSomething()读取自己的A字段时,拿到的就是子类A1的值了。不过这种方式耦合度比较高,子类和父类的字段绑定在了一起,扩展性稍差。
关键知识点:Java不能重写字段名称
这里要明确一点:Java里不存在“重写字段名称”的说法。子类定义的A1只是新增了一个完全独立的字段,和父类的A没有任何关联。哪怕子类定义了同名的字段(这叫“字段隐藏”),父类的方法也只会访问自己类中定义的字段,不会用到子类的同名字段,更别说不同名称的字段了。所以必须通过重写方法的方式,让父类的逻辑转向子类的变量。
内容的提问来源于stack exchange,提问作者ubernal

