这还是多态吗?

时间:2012-06-19 15:55:28

标签: java inheritance polymorphism

编码时,我对多态性产生了一个有趣的疑问,我无法理解这个问题。

public class Animal {
  public void getLegs() {
    SOP("4 legs"); 
  }
}

public class Kangaroo extends Animal {
  public void getLegs() {
    SOP("2 legs"); 
  }
  public static void main(String[] args) {
    Animal a = new Kangaroo(); // without changing this how can I get Animal getLegs
    SOP(a.getLegs()); // Important Line
  }
}

现在如果我想调用getLegs的{​​{1}}方法,我该怎么办?可能吗?它仍然是多态的吗?

5 个答案:

答案 0 :(得分:3)

是的,这是展示多态性的最基本形式。

基本上您正在处理名为Animal的{​​{1}}。当您调用a时,您的代码不会绑定到a.getLegs()getLegs()的实现,而是绑定到{{1}中的最低子类实现Animal }}

如果getLegs()有一个实现,则子类实现称它为 hidden 。如果Kangraoo()没有实现,则无法构建Animal的独立类,因为它们缺少所有必需方法的实现,并且在这种情况下,Animal是据说是一个抽象类(一个不能直接构造,但只能由它的子类构造)。

答案 1 :(得分:2)

如果您真的想要为Animal调用方法,并且可以使用静态方法,则可以使用隐藏而不是覆盖。

它的工作原理如下:对于静态方法,被调用的方法是与声明的类型相关的方法,而不是对象实例。换句话说,它遵循类,因为该方法是类方法,而不是实例方法。

一个改编自this page的例子:

public class Animal {
  public static void testClassMethod() {
      System.out.println("The class" + " method in Animal.");
  }
  public void testInstanceMethod() {
      System.out.println("The instance " + " method in Animal.");
  }
}

public class Kangaroo extends Animal {
  public static void testClassMethod() {
      System.out.println("The class method" + " in Kangaroo.");
  }
  public void testInstanceMethod() {
      System.out.println("The instance method" + " in Kangaroo.");
  }

  public static void main(String[] args) {
      Kangaroo myRoo = new Kangaroo();
      Animal myAnimal = myRoo;
      myRoo.testInstanceMethod();
      myAnimal.testInstanceMethod();
      Kangaroo.testClassMethod();
      Animal.testClassMethod();
  }
}

结果将是(注意第3和第4行,而不是第1和第2行):

The instance method in Kangaroo.
The instance method in Kangaroo.
The class method in Kangaroo.
The class method in Animal.

答案 2 :(得分:1)

在Java中,无法访问Animal的实现。它将永远返回袋鼠的版本。

(注意在C#中 可以通过用“new”标记覆盖方法来实现,但它是一个相当专业的用例)。

访问似乎是Animal的东西,但获得Kangaroo指定的行为正是多态性的原因 - 子对象在其父对象所在的任何地方都可以被替换。

通常,您不希望让调用代码知道继承层次结构,因为这会将代码紧密地耦合在一起。如果你真的需要访问Animal的这种方法的实现,它表明你的设计可能是错误的。

答案 3 :(得分:1)

  

现在如果我想调用Animal的getLegs方法,我该怎么办?有可能吗?

如果要访问被覆盖的方法 - 这与多态性相矛盾 - 您可以使用反射。从getLegs的类中获取Animal方法,然后在Kangaroo对象上调用它。但是,这是一个黑客攻击,而不是你在常规程序中所做的事情。

SOP( Animal.class.getMethod("getLegs").invoke(a) );

答案 4 :(得分:1)

多态性的精神是执行在运行时决定的不同代码。为了更清楚,我会稍微修改你的代码。

    public class Animal {

    public void getLegs(){
      SOP('4 legs'); 
     }

}
public class Kangaroo extends Animal{
 public void  getLegs(){
      SOP('2 legs'); 
  }
public static void main(String[] args){
  Animal a = new Kangaroo(); //without changing this how can I get Animal getLegs
  Kangaroo kng= new Kangaroo ();
  Animal an = new Animal();

  SOP(a.getLegs());  // Kangaroo's version is called
  SOP(kng.getLegs()); //Again, Kangaroo's version is called
  SOP(an.getLegs());   //Animal version is called

  }
}

并且是的,正如所有人说你不能从你的Animal a = new Kangaroo();行调用动物......因为没有人会想要这样做。相反,他会直接写。 Animal a = new Animal(); ..

所以最后是决定哪个方法被称为

的对象而不是referance