java – 为什么它在子类对象中为超类变量存储或分配内存?

在以下代码中 –

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());
   }
}

如果我在eclipse的调试窗口中看到,两个对象(m和z)都包含name变量(furry和stripe)的值.

我知道在多态中,超类的泛型方法也可以被子类使用.但是,为什么子类对象也存储超类变量的值,即使在隐藏的情况下也是如此.这有什么用吗?

解决方法:

第一:作为一般规则,如果类定义了子类可以访问的字段,则子类不应重新定义该字段.这只是一个真正糟糕的主意.主要是你所看到的是让私人领域正常运作.重新定义子类中的非私有字段是一个受到伤害的世界. (当然,如果Joe写Mammal和Mary写Zebra并且在某些时候Joe为Mammal添加了一个与Mary在Zebra中使用的字段冲突的字段,那么Mary就无法做到这一点.这是制作所有字段的原因之一私人的.)

But why does sub class object stores values of super class variables as well, even in case of hiding.

这里的关键是要记住字段不是多态的,只是方法.因此,对象中必须有两个名称字段(一个来自Mammal,一个来自Zebra),因为使用Mammal类型引用的代码需要查看Mammal名称,而使用Zebra类型引用的代码需要查看Zebra名称.

这就是为什么你的代码显示“毛茸茸的bray”然后“条纹bray”.你通过m获得“毛茸茸的bray”,因为访问m上的名字(一个哺乳动物类型的变量)访问Mammal的名字(不是多态),给你“毛茸茸”.但是你用m调用方法makeNoise然后回来“bray”,因为被调用的方法是Zebra上的方法(多态).然后你用z(一个Zebra类型的引用)再次执行它并看到“条纹bray”因为z访问Zebra的名字,而不是Mammal的名字.

您可能遇到的下一个问题是:如果我们将两个类中的makeNoise更改为:

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());

从z的m条纹条纹给我们“毛茸茸的条纹”?

这也是同样的原因,只是对它的不同表现. m.name从Mammal类型的引用中访问名称,因此可以看到Mammal的名称(不是多态). m.makeNoise调用Zebra的makeNoise方法(多态),在Zebra的makeNoise中,它有Zebra类型,即使我们从Mammal类型的m调用它(因此this.name使用Zebra的名字). Zebra的makeNoise在那里使用的事实,以及Zebra代码中的类型Zebra这一事实都是Java中多态性的关键.

让我们进一步说明:如果Zebra根本没有定义makeNoise怎么办?

class Mammal {
    String name = "furry ";
    String makeNoise() { 
        return this.name;
    }
}

class Zebra extends Mammal {
    String name = "stripes ";
}

现在我们从m得到“毛茸茸的毛茸茸”,从z得到“条纹毛茸茸”.它的原因与上面相同:引用的类型决定了使用哪个字段,而在哺乳动物代码(makeNoise)中,它的类型为Mammal.因此即使我们使用z调用makeNoise,因为Zebra没有makeNoise,所以调用Mammal,所以查找name的引用具有类型Mammal.

Is there any use of this?

课程正常工作至关重要,特别是在私人领域.哺乳动物代码不必担心出现的子类并重新定义其字段.你可以拥有一个10深的类层次结构,每个类定义自己的名称,这很好,每个级别的代码都使用它定义的名称.

上一篇:如何从JavaScript中的子类调用父类的方法,以便可以访问父的局部变量?


下一篇:java – 超类中的受保护方法在不同包中的子类中是否可见?