JAVA: 子类“覆盖”父类的成员变量
在实际工程中,遇到一个问题,子类需要继承父类的所有方法,但是成员变量不一样,需要覆盖父类的成员变量。
public class Base { private static final String gun = "ak48"; public void fire(){ System.out.println(gun); } } public class Derived extends Base { private static final String gun = "M1917"; public static void main(String[] args) { new Derived().fire(); } }
我们希望开火的时候用M1917,而真正用的是ak48,那怎么才能不重新建一个基站就能直接用M1917呢?
Java本身是不提供覆盖父类的成员变量的,为什么呢?
答:实际上,即使子类声明了与父类完全一样的成员变量,也不会覆盖掉父类的成员变量。而是在子类实例化时,会同时定义两个成员变量,子类也可以同时访问到这两个成员变量,但父类不能访问到子类的成员变量(父类不知道子类的存在)。而具体在方法中使用成员变量时,究竟使用的是父类还是子类的成员变量,则由方法所在的类决定;即,方法在父类中定义和执行,则使用父类的成员变量,方法在子类中定义(包括覆盖父类方法)和执行,则使用子类的成员变量。
但是我们实际中就有这种需求,有几种途径可以解决这个问题:
1.提供get方法
public class Base { private String gun = "ak48"; public String getGun() { return gun; } public void setGun(String gun) { this.gun = gun; } public void fire(){ System.out.println(getGun()); } } public class Derived extends Base { private String gun = "M1917"; @Override public String getGun() { return gun; } @Override public void setGun(String gun) { this.gun = gun; } public static void main(String[] args) { new Derived().fire(); } }
原理:父类的 fire()开火函数调用的实际上是子类重写的getGun()方法,拿的是子类的成员变量。但实际上还是有二个成员变量存在。
2.通过修改父类成员变量
public class Base { protected String gun = "ak48"; public void fire(){ System.out.println(gun); } } public class Derived extends Base { private String gun = "M1917"; Derived(){ super.gun = gun; } public static void main(String[] args) { new Derived().fire(); } }
输出:M1917
这个就是利用super在子类构造函数中初始化父类的成员变量
3.static代码块
public class Base { protected static String gun = "ak48"; public void fire(){ System.out.println(gun); } } public class Derived extends Base { static { gun = "M1917"; } public static void main(String[] args) { new Derived().fire(); } }
static
块会在类初始化而不是实例化时被执行,而父类中的static
成员变量会在子类static
块执行前就定义完成,所以子类初始化时会修改父类的成员变量值,子类实例化时自然得到的父类成员变量值也是修改过的,这样完成了“覆盖”。
static
块恰恰是利用了JAVA会无条件执行staitc
块这一特性,达到了这个目的。这种方法说坏处的话,估计就是成员变量必须是static
了。
文章参考来源:https://www.polarxiong.com/archives/JAVA-%E5%AD%90%E7%B1%BB-%E8%A6%86%E7%9B%96-%E7%88%B6%E7%B1%BB%E7%9A%84%E6%88%90%E5%91%98%E5%8F%98%E9%87%8F.html