英文:
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.z
与 A.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).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论