为什么它在子类对象中为超类变量存储或分配内存? [英] Why does it store or allocate memory for super class variables, in sub class object?
问题描述
在以下代码中 -
class Mammal {
String name = "furry ";
String makeNoise() {
return "generic noise";
}
}
class Zebra extends Mammal {
String name = "stripes ";
String makeNoise() {
return "bray";
}
}
public class ZooKeeper {
public static void main(String[] args) {
new ZooKeeper().go();
}
void go() {
Mammal m = new Zebra();
System.out.println(m.name + m.makeNoise());
Zebra z = new Zebra();
System.out.println(z.name + z.makeNoise());
}
}
两个对象( m
和 z
),如果我在eclipse的调试窗口中看到,包含 name的值
变量(毛茸茸
和条纹
)。
Both objects (m
and z
), if I see in debug windows of eclipse, contain both values of name
variable (furry
and stripes
).
我明白在多态性中,超类的泛型方法也可以被子类使用。但是,为什么子类对象也存储超类变量的值,即使在隐藏的情况下也是如此。这有什么用吗?
I do understand that in polymorphism, generic method of super class can be used by sub class as well. But why does sub class object stores values of super class variables as well, even in case of hiding. Is there any use of this?
推荐答案
首先:作为一般规则,如果一个类定义了一个子类可以访问的字段,子类不应重新定义该字段。这只是一个真正糟糕的主意。您所看到的主要是让私有字段正常工作。重新定义子类中的非私有字段是为了要求一个受伤的世界。 (当然,如果Joe写 Mammal
并且Mary写 Zebra
并且在某些时候Joe将字段添加到 Mammal
碰巧与Mary在 Zebra
中使用的那个冲突,玛丽无法做到这一点。这是制作的一个原因所有字段都是私有的。)
First: As a general rule, if a class defines a field that a subclass can access, the subclass should not redefine the field. It's just a Really Bad Idea. Primarily what you're seeing is there to make private fields work properly. Redefining non-private fields in a subclass is asking for a world of hurt. (Of course, if Joe writes Mammal
and Mary writes Zebra
and at some point Joe adds a field to Mammal
that happens to conflict with one that Mary used in Zebra
, there's nothing Mary can do about that. Which is one reason for making all fields private.)
但是为什么子类对象也存储超类变量的值,即使在隐藏的情况下也是如此。
But why does sub class object stores values of super class variables as well, even in case of hiding.
这里的关键是要记住字段不是多态的,只是方法。所以 是对象中的两个 name
字段(一个来自 Mammal
和一个来自 Zebra
),因为使用 Mammal
-typed参考的代码需要查看 Mammal
name
,而使用 Zebra
-typed引用的代码需要查看 Zebra
name
。
The key here is to remember that fields are not polymorphic, just methods. So there have to be two name
fields in the object (one from Mammal
and one from Zebra
), because code using a Mammal
-typed reference needs to see the Mammal
name
, whereas code using the Zebra
-typed reference needs to see the Zebra
name
.
这就是为什么你的代码显示毛茸茸的bray和然后条纹布雷。你通过 m
得到毛茸茸的,因为在 m $ c $上访问
name
c>(一个 Mammal
-typed变量)访问哺乳动物
的名称
(不是多态的),给你毛茸茸。但是你使用 m
调用方法 makeNoise
并返回bray
,因为被调用的方法是 Zebra
(多态)上的方法。然后你再次使用 z
(一个 Zebra
-typed参考)并看到stripe bray,因为 z
访问 Zebra
的名称
,而非哺乳动物
's。
That's why your code shows "furry bray" and then "stripes bray". You get "furry bray" via m
because accessing name
on m
(a Mammal
-typed variable) accesses Mammal
's name
(not polymorphic), giving you "furry". But then you call the method makeNoise
using m
and get back "bray"
, because the method that gets called is the one on Zebra
(polymorphic). Then you do it again with z
(a Zebra
-typed reference) and see "stripes bray" because z
accesses Zebra
's name
, not Mammal
's.
您可能遇到的下一个问题是:如果我们更改<$两个类中的c $ c> makeNoise :
The next question you might have is: If we change makeNoise
in both classes to:
String makeNoise() {
return this.name;
}
为什么 ZooKeeper
代码
Mammal m = new Zebra();
System.out.println(m.name + m.makeNoise());
Zebra z = new Zebra();
System.out.println(z.name + z.makeNoise());
从 m
给我们毛茸茸的条纹和条纹条纹
来自 z
?
give us "furry stripes" from m
and stripes stripes
from z
?
它是一样的原因,只是一个不同的介绍。 m.name
从 Mammal
-typed参考访问 name
,所以看到哺乳动物
的名称
(不是多态的)。 m.makeNoise
致电 Zebra
的 makeNoise
方法(多态),内部 Zebra
的 makeNoise
,此
的类型为 Zebra
,即使我们从 Mammal
-typed <$ c $调用它c> m (以及 this.name
使用 Zebra
的名称
)。在那里使用Zebra的 makeNoise
,以及
Zebra code>代码类型
Zebra
都是Java中多态性的关键。
It's the same reason, just a different presentation of it. m.name
accesses name
from a Mammal
-typed reference, and so sees Mammal
's name
(not polymorphic). m.makeNoise
calls Zebra
's makeNoise
method (polymorphic), and inside Zebra
's makeNoise
, this
has the type Zebra
even though we called it from a Mammal
-typed m
(and so this.name
uses Zebra
's name
). The fact that Zebra's makeNoise
is used there, and the fact that this
within Zebra
code is typed Zebra
are both key to polymorphism in Java.
让我们进一步说明:如果 Zebra
根本没有定义 makeNoise
怎么办?
Let's take it further: What if Zebra
doesn't define makeNoise
at all?
class Mammal {
String name = "furry ";
String makeNoise() {
return this.name;
}
}
class Zebra extends Mammal {
String name = "stripes ";
}
现在我们从 m <得到毛茸茸的毛茸茸 / code>和来自
z
的条纹毛茸茸。它的原因与上面相同:引用的类型决定了使用哪个字段,以及 Mammal
代码( makeNoise
),此
的类型为 Mammal
。所以即使我们使用 z
调用 makeNoise
,因为 Zebra
没有 makeNoise
,调用Mammal
,所以查找 name <的引用/ code>的类型为
Mammal
。
Now we get "furry furry" from m
and "stripes furry" from z
. And the reason for it is the same as above: The type of the reference determines which field is used, and in Mammal
code (makeNoise
), this
has the type Mammal
. So even though we called makeNoise
using z
, since Zebra
has no makeNoise
, Mammal
's is called, so the reference that looks up name
has the type Mammal
.
有什么用这个?
Is there any use of this?
对于正常工作的类来说,至关重要,特别是在私有字段的情况下。 Mammal
代码不必担心出现的子类并重新定义其字段。你可以有一个10深的类层次结构,每个类定义自己的名称
,这很好,每个级别的代码都使用名称
它定义。
It's crucial to classes working properly, particularly in the case of private fields. Mammal
code doesn't have to worry about a subclass coming along and redefining its fields. You could have a 10-deep class hierarchy, with each class defining its own name
, and that's fine, each level's code works with the name
it defines.
这篇关于为什么它在子类对象中为超类变量存储或分配内存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!