4

一般来说,重写是在子类中重新定义成员的含义的概念。为什么在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=" + b.a);
    }
}

由于数据成员a是指定的包访问权限,因此它也可用于Derived类。但是一般在使用基类引用调用被覆盖的方法时,在派生类中重新定义的方法被调用(动态方法分派)..但是变量不一样..为什么。

预期输出

内部派生:
a=99

获得的输出:

内部派生:
a=10

打印 10 - 为什么变量的行为与派生类中的方法不同?
为什么不允许在子类中覆盖变量?

4

10 回答 10

6

b作为Base. 所以当编译器需要解析的时候b.a,它会查找Basefor 的定义b.a。实例字段没有多态性。

于 2013-06-19T21:06:25.973 回答
2

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

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

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

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

于 2013-06-19T21:06:43.157 回答
2

变量的行为是这样的,因为它们缺乏行为。换句话说,变量是被动的。

派生类可以通过重写来合理地改变变量的定义:

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

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

于 2013-06-19T21:06:44.337 回答
1

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

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

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

于 2013-06-19T21:17:00.923 回答
1

没有办法覆盖类变量。您不会覆盖 Java 中的类变量,而是隐藏它们。覆盖是实例方法。

于 2013-06-19T21:04:51.497 回答
1

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

public int getA(){
  return 99;
}

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

于 2013-06-19T21:08:21.503 回答
0

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

派生类也不应该再次定义 a,它已经在基类中定义了,所以只需将对象上的 a 设置为所需的值,例如:

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
于 2013-06-19T22:52:20.197 回答
0

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

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

class Base {
    int a = 10;
}

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

当然,这不适用于final变量。

于 2013-07-21T03:22:28.353 回答
0
  1. we don't override any class variable. Methods only.
  2. If you would like to see that the variable value has been updated or replaced, you should rather declare it as "static int" instead of "int". In this way, it will work as everybody is sharing the same variable, and the new value will be put on it.
  3. If you would like to see that the variable value being assigned and used differently, you could design it as passing a parameter in constructor, or something similar, to make it work accordingly as you desire.

Moreover, if variables are overridden then what is left with a parent class of its own,it breaches the class security if java would give the access to change the value of variable of parent class.

于 2013-07-21T03:32:10.700 回答
0

这个问题的答案与变量作用域有关,而不是多态性。换句话说,您在类范围内覆盖了该变量。因此,d.a将返回Derived's 类范围内的变量,但b.a将返回Base's 类范围内的变量。

于 2013-06-19T21:07:47.887 回答