请参阅下面的代码,其中的方法print被覆盖,但变量a没有被覆盖。为什么允许在子类中声明重复的变量?
print
a
class B { int a = 10; public void print() { System.out.println("inside B superclass"); } } class C extends B { int a = 20; public void print() { System.out.println("inside C subclass"); } } public class A { public static void main(String[] args) { B b = new C(); b.print(); // prints: inside C subclass System.out.println(b.a); // prints superclass variable value 10 } }
为什么在子类方法中不覆盖超类的实例变量,请参见下面的代码…
因为实例变量不能在Java中覆盖。在Java中,只能重写方法。
当你声明一个与超类中现有字段同名的字段时,新字段将隐藏现有字段。超类中的现有字段仍存在于子类中,甚至可以使用…遵守常规的Java访问规则。
因为实例变量在Java中无法被覆盖,但是为什么呢?为什么在Java中以这种方式完成?什么原因?
他们为什么这样设计?
例如:
public class Sup { private int foo; public int getFoo() { return foo; } } public class Sub extends Sup { private int[] foo; ... }
如果Sub.foo覆盖(即替换)Sup.foo,如何getFoo()工作?在子类上下文中,它将试图返回错误类型的字段的值!
如果被覆盖的字段不是私有字段,那就更糟了。这将以相当根本的方式打破《里斯科夫可替代性原则》。这就消除了多态性的基础。
在另一面,覆盖领域起不到任何能不能做到更好的在其他方面。例如,一个好的设计将所有实例变量都声明为私有,并根据需要为其提供getter / setter方法。可以覆盖getter / setter ,并且直接使用私有字段或声明getter / setter的父类可以“保护”自身免受不希望的覆盖final。