本文介绍了为什么它在子类对象中为超类变量存储或分配内存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在以下代码中 -

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.)

这里的关键是要记住字段不是多态的,只是方法。所以 是对象中的两个 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>(一个 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 和来自 z 的条纹毛茸茸。它的原因与上面相同:引用的类型决定了使用哪个字段,以及 Mammal 代码( makeNoise ),此的类型为 Mammal 。所以即使我们使用 z 调用 makeNoise ,因为 Zebra 没有 makeNoise ,调用Mammal ,所以查找 name 的类型为 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.

对于正常工作的类来说,至关重要,特别是在私有字段的情况下。 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.

这篇关于为什么它在子类对象中为超类变量存储或分配内存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 16:36