基类引用的意外多态行为

时间:2013-10-09 09:24:46

标签: java polymorphism

我写了这段代码

class Flower{
  String name = "Flower";
  void print(){System.out.println("Flower method");}
}

class Rose extends Flower{
  String name = "Rose";
  void print(){System.out.println("Rose method");}
}

....
//Another class in same default package
public static void main(String... args){
  Flower f = new Rose();
  f.print();
  System.out.println(f.name);
}

我正在考虑此代码的输出为:

Flower method
Flower

但是打印

Rose method
Flower

我的经验法则是,当您使用其中一种“较小”类型作为参考时,只有它们的成员在对象中可见。您将需要强制转换才能访问其余部分。但似乎方法的处理方式不同?

5 个答案:

答案 0 :(得分:3)

Ahaaa ..多态性。 OOP的一个更好的功能。分步说明:

  1. 您使用的是单个继承,其中类Rose派生类Flower基类
  2. 如果你的超类和派生类中的方法具有相同的名称,默认情况下,会调用派生类的方法,而不是超类的方法。默认情况下,它们为Over-ridden
  3. 超类中的字段不能通过其简单名称引用。相反,必须通过super。
  4. 访问该字段

    你得到了输出,因为:

    1. f.print()会调用 Rose 的方法,而不是 Flower 。如果您需要拨打print()花,可以相应地使用super.print()
    2. f.name正在打印Flower,因为f的类型为Flower而非Rose。您可以使用方法来访问它,如:
      public String getName()
      {
        return this.name;
      }
    3. 并相应地使用它:System.out.println(f.getName);

      编辑:要以外行的方式理解,@Juned Ahsan的回答非常简单明了:

      Flower f = new Rose();
      

      由于f是新的Rose,语句f.print()将调用Rose的方法。

      认为值得一提。 :)

      尝试阅读多态性。有很多参考文献。 :)

答案 1 :(得分:2)

字段不像方法那样是多态的

这里混淆了相同的字段名称。

Java language specification#shadowing.

Docs

  

在类中,与超类中的字段具有相同名称的字段会隐藏超类的字段,即使它们的类型不同。在子类中,超类中的字段不能通过其简单名称引用。相反,必须通过super

访问该字段

因此,在您的情况下,超级calss name

隐藏的Rose类字段Flower

答案 2 :(得分:1)

Flower f = new Rose();

由于f持有Rose的对象,因此在调用时会调用Rose的覆盖方法:

  f.print();

并打印Rose method

f是一个花卉参考,覆盖是仅methods的概念而不是实例字段的概念,因此

  System.out.println(f.name);

将打印Flower

答案 3 :(得分:0)

你正在重写Rose课程中类Flower的打印方法。这就是你得到这个输出的原因。

答案 4 :(得分:0)

当您使用“动态多态”时,超类引用保存子类对象。在你的情况下,Rose对象是f。

Flower f = new Rose();
          f.print();

当你调用print方法时,它实际上在Rose类中调用了print方法。