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

时间:2013-06-19 20:59:42

标签: java inheritance override

一般来说,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=" + b.a);
    }
}

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

预期输出

内部衍生:
a = 99

获得的输出:

内部衍生:
a = 10

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

10 个答案:

答案 0 :(得分:6)

您输入b作为Base的实例。因此,当编译器需要解析b.a时,它会查找Baseb.a含义的定义。实例字段没有多态性。

答案 1 :(得分:2)

因为多态 仅适用于Java的实例方法

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

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

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

答案 2 :(得分:2)

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

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

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

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

答案 3 :(得分:1)

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

答案 4 :(得分:1)

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

public int getA(){
  return 99;
}

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

答案 5 :(得分:1)

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

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

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

在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

答案 8 :(得分:0)

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

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

class Base {
    int a = 10;
}

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

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

答案 9 :(得分:0)

  1. 我们不会覆盖任何类变量。仅限方法。
  2. 如果您希望看到变量值已更新或 替换后,您应该将其声明为“static int”而不是 “INT”。通过这种方式,它将起作用,因为每个人都在分享相同的东西 变量,新值将被放在上面。
  3. 如果您希望看到分配的变量值和 换句话说,您可以将其设计为传递参数 构造函数或类似的东西,使其相应地工作 你渴望。
  4. 此外,如果变量被覆盖,那么剩下的是自己的父类,如果java允许访问权限更改父类变量的值,则会破坏类安全性。