为什么超类的实例变量没有在子类方法中重写

Jay*_*esh 36 java

为什么超类的实例变量没有在子类方法中被覆盖,请参阅下面的代码..在哪个方法中打印被覆盖但是变量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中以这种方式完成?什么原因?

他们为什么这样设计呢?

  1. 因为重写变量会从根本上打破超类中的代码.例如,如果覆盖更改了变量的类型,则可能会更改使用原始变量的父类中声明的方法的行为.最糟糕的是,它使它们无法编译.

    例如:

       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()工作?在子类上下文中,它将尝试返回错误类型的字段的值!

  2. 如果被覆盖的字段不是私有的,那就更糟了.这将以一种非常基本的方式打破Liskov Substitutability Principle(LSP).这消除了多态性的基础.

  3. 另一方面,重写字段无法实现在其他方面无法做得更好的任何事情.例如,一个好的设计将所有实例变量声明为私有,并根据需要为它们提供getter/setter.可以覆盖getter/setter ,并且父类可以通过直接使用私有字段或声明getter/setter来"保护"自身免受不良覆盖final.


参考文献: