关于Java行为的推理。

huangapple go评论70阅读模式
英文:

Reasoning Behind this Java Behaviour

问题

obj.z gives A's z because the variable z is shadowed in class B. Shadowing occurs when a subclass defines a variable with the same name as a variable in its superclass. In such cases, the variable in the subclass hides the variable in the superclass.

When you create an object of type A but initialize it with an instance of class B like this:

A obj = new B();

The type of the reference variable obj is still A, which means it can only access members (variables and methods) that are part of class A. Even though the actual object being referred to is of type B, the reference type determines which members are accessible.

So, when you access obj.z, it refers to the variable z in class A because the reference type is A. This behavior ensures that you can rely on the members of the reference type when working with polymorphic objects, which is a fundamental concept in object-oriented programming.

However, when you call obj.display(), it uses dynamic method dispatch (polymorphism) to determine the appropriate method to invoke based on the actual object type, not the reference type. In this case, the object being referred to is of type B, so it calls the display() method from class B, which prints out "B's z is 20".

To summarize, variable access is determined by the reference type, while method invocation is determined by the actual object type, which is why you observe different behavior for obj.z and obj.display().

英文:

CONTEXT

say we have a class inheritance structure like this

class A {
    int z = 10;

    public void display() {
        System.out.println("A's z is " + z);
    }
}

class B extends A {
    int z = 20;

    public void display() {
        System.out.println("B's z is " + z);
    }

    public void onlyB() {
        System.out.println("This is only in B");
    }
}

class Main {

    public static void main(String args[]) {
        A obj = new B();

        System.out.println(obj.z); // 10
        obj.display(); // B's z is 20
    }
}

QUESTION

Why does obj.z gives A's z but obj.display() uses B's z, is there a way to think about this so that it makes sense logically?

ATTEMPTS AT UNDERTANDING

by saying

A obj = new B();

In my mind, this is saying "create an object of type A, but use al of B's implementations"

by that reasoning, it is logical that the object cannot use onlyB() because it is of type A, and A does not have onlyB(). also by that reasoning, display() would use B's implementation. But why does calling z use A's z instead of B's? shouldn't the object use B's implementation of z?

I know this wont appear in practice but I am very curious to know. A better spelled out explanation as to why this happens would be appreciated.

答案1

得分: 1

你引入了变量屏蔽。字段 B.zA.z 不同(并且是继承的,但屏蔽了 A.z)。但如果你将它从

class B extends A {
    int z = 20;

更改为类似于

class B extends A {
    public B() {
        this.z = 20;
    }

那么实际上就是继承,只会有一个 z

英文:

You have introduced a variable shadow. The field B.z is distinct from A.z (and inherited, but shadowing the A.z). But if you change it from

class B extends A {
    int z = 20;

to something like

class B extends A {
    public B() {
        this.z = 20;
    }

Then it's actually inheritance and there will only be a single z.

答案2

得分: 1

在Java(以及我所了解的大多数编程语言中),字段不会被覆盖。因此,如果在父类中定义了一个字段,在子类中定义了另一个具有相同名称的字段,那么这两个字段都会存在(并且每个字段可以在其类内部正常访问)。 (考虑将在B中定义的z定义为String而不是int!现在它们具有不同的类型,而B看到的是一个Stringz)。

但是,非静态方法可以被覆盖。

当你有A obj = new B()时,你拥有一个B的实例,但使用的是A类型的引用。当访问字段(这些字段不可覆盖)时,你访问的是A.z,但当调用方法(它被覆盖了),实际调用的方法是通过动态查找表查找的,调用了B的方法(这就是继承的威力所在),并且该方法访问它自己的z。(再次考虑将B中的z定义为String,那么obj.z的类型是int而不是obj的类型类中的String)。

英文:

In Java (and most languages I know), fields are not overriden. So if you define a field in parent class and other field in child class with same name, both fields will exists there (and each one can be accessed normally within its class). (Consider defining your z in B as String not int! now they have different types, and B sees a String z).

But non-static methods can be overriden.

When you have A obj = new B() you are having an instance of B, but with a reference of type A. When accessing the fields (which are not overridable), then your are accessing A.z, but when you call the method (which is overriden), the real method which is called lookup through a dynamic lookup table and B's method get called (that's the power of inheritance), and the method accesses it's own z. (Again consider z in B be of String, then obj.z is of type int not String which is in the obj's type class).

huangapple
  • 本文由 发表于 2023年6月4日 22:59:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76401006.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定