为什么超类的实例变量没有在子类方法中被覆盖,请参阅下面的代码..在哪个方法中打印被覆盖但是变量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
}
}
Run Code Online (Sandbox Code Playgroud)
Ste*_*n C 41
为什么超类的实例变量没有在子类方法中重写,请参阅下面的代码...
因为实例变量不能在Java中重写.在Java中,只能覆盖方法.
声明与超类中现有字段同名的字段时,新字段会隐藏现有字段.来自超类的现有字段仍然存在于子类中,甚至可以使用...遵循普通的Java访问规则.
因为实例变量不能在Java中重写,但为什么呢?为什么在Java中以这种方式完成?什么原因?
他们为什么这样设计呢?
因为重写变量会从根本上打破超类中的代码.例如,如果覆盖更改了变量的类型,则可能会更改使用原始变量的父类中声明的方法的行为.最糟糕的是,它使它们无法编译.
例如:
public class Sup {
private int foo;
public int getFoo() {
return foo;
}
}
public class Sub extends Sup {
private int[] foo;
...
}
Run Code Online (Sandbox Code Playgroud)
如果Sub.foo覆盖(即替换)Sup.foo,如何getFoo()工作?在子类上下文中,它将尝试返回错误类型的字段的值!
如果被覆盖的字段不是私有的,那就更糟了.这将以一种非常基本的方式打破Liskov Substitutability Principle(LSP).这消除了多态性的基础.
另一方面,重写字段无法实现在其他方面无法做得更好的任何事情.例如,一个好的设计将所有实例变量声明为私有,并根据需要为它们提供getter/setter.可以覆盖getter/setter ,并且父类可以通过直接使用私有字段或声明getter/setter来"保护"自身免受不良覆盖final.
参考文献:
| 归档时间: |
|
| 查看次数: |
32072 次 |
| 最近记录: |