为什么变量在覆盖时的行为与方法不同?

通常,Overriding是在子类中重新定义成员含义的概念。为什么变量在重写java时不像方法一样?
例如:

class Base { int a = 10; void display() { System.out.println("Inside Base :"); } } class Derived extends Base { int a = 99; @Override // method overriding void display() { System.out.println("Inside Derived :"); } } public class NewClass { public static void main(String... a) { Derived d = new Derived(); Base b = d; b.display(); // Dynamic method dispatch System.out.println("a=" + ba); } } 

由于数据成员a是指定的包访问,因此Derived类也可以使用它。 但通常在使用基类引用调用重写方法时,会调用派生类中重新定义的方法(动态方法调度)..但对于变量..why,它是不一样的。

预期输出

内部派生:
一个= 99

获得的输出:

内部派生:
A = 10

打印10 – 为什么变量的行为与派生类中的方法不相似?
为什么不允许在子类中重写变量?

您键入b作为Base的实例。 因此,当编译器需要解析ba ,它会根据ba的含义来定义Base的定义。 实例字段没有多态性。

因为多态性在Java中唯一适用的是实例方法

因此,您既不能覆盖静态成员,也不能覆盖实例成员字段。 通过将这些成员放在具有相同名称的派生类中,您只需使用新定义隐藏它们。

 System.out.println("a="+ba); 

虽然, Base b可能指向一个子类对象(在运行时), a上面的a已经在编译时绑定到Base类(静态绑定)。 因此,它打印10。

变量的行为与此类似,因为它们缺乏行为。 换句话说,变量是被动的。

变量的定义没有任何内容可以通过覆盖来合理地改变派生类:

  • 它不能改变它的类型,因为这样做可能会破坏基类的方法;
  • 它无法降低其可见性,因为这会破坏替代原则。
  • 如果不对基类无用,它就无法成为final

因此,在派生类中声明的成员变量会隐藏基类中的变量。

无法覆盖类变量。 您不会在Java中覆盖隐藏它们的类变量。 覆盖是例如方法。

在这种情况下,编写getter方法可能是个好主意:

 public int getA(){ return 99; } 

现在,您可以在派生类中覆盖它。

首先,我们不会覆盖任何类变量。 仅限方法。

其次,如果您希望看到变量值已被更新或替换,您应该将其声明为“static int”而不是“int”。 通过这种方式,它将工作,因为每个人都在共享相同的变量,并且新值将被放在其上。

第三,如果您希望看到变量值的分配和使用方式不同,您可以将其设计为在构造函数中传递参数或类似的东西,以使其按您的需要相应地工作。

答案就是变量范围,而不是多态。 换句话说,您将覆盖类范围中的该变量。 因此, da将返回Derived的类范围中的变量,但是ba将返回Base的类范围中的变量。

在OOP(面向对象编程)中,我们的想法是隐藏对象中的数据,让对象只与调用方法进行通信。 这就是为什么变量不能重载的原因,实际上它们是“作用域”/“附加”到特定的类。

此外,派生类不应再次定义,它已经在基类中定义,因此只需将对象设置为所需的值,例如:

 class Base { private int a = 10; public int getA() { return a; } public void setA(inta) { this.a = a; } } class Derived extends Base { // adding new variables, override methods, ... } // then later: Derived d = new Derived(); d.setA(99); // override the default value 10 

如果变量可以覆盖其他变量会发生什么? 突然你的类必须知道父类正在使用什么变量 ,以免你不小心覆盖一个并破坏在父类中使用它的任何东西。 封装的全部意义在于避免对另一个对象的内部状态有这种亲密的了解。 因此,变量会影响同名的其他变量,您看到的变量取决于您尝试通过哪种类型变量。

但是有希望。 如果您只想覆盖该值,则无需重新声明该变量。 只需更改 init块中的值即可 。 如果您这样做会损害基类,那么它会为该变量选择错误的可见性。

 class Base { int a = 10; } class Derived extends Base { { a = 99; } } 

当然,这对final变量不起作用。

  1. 我们不会覆盖任何类变量。 仅限方法。
  2. 如果您希望看到变量值已被更新或替换,您应该将其声明为“static int”而不是“int”。 通过这种方式,它将工作,因为每个人都在共享相同的变量,并且新值将被放在其上。
  3. 如果您希望看到变量值的分配和使用方式不同,您可以将其设计为在构造函数中传递参数或类似的东西,以使其按您的需要相应地工作。

此外,如果变量被覆盖,那么剩下的是自己的父类,如果java赋予访问权限以更改父类的变量值,则会破坏类安全性。