2

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

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方法Animal,我该怎么做?是否可以?还是多态吗?

4

5 回答 5

3

是的,它是演示多态性的最基本形式。

基本上你正在处理一个Animal命名的a. 当您调用a.getLegs()您的代码时,它不会绑定到getLegs()in的实现Animal,而是绑定到最低的子类实现getLegs()in Kangraoo()

如果Animal有一个实现,就说它被子类实现隐藏了。如果Animal没有实现,那么就不可能构造独立的类,Animal因为它们缺少所有必需方法的实现,在这种情况下,Animal被称为抽象类(不能直接构造,但是只能由它的子类构造)。

于 2012-06-19T15:57:51.743 回答
2

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

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

一个例子,改编自这个页面

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.
于 2012-06-19T16:15:38.353 回答
1

在 Java 中,无法访问 Animal 的实现。它总是会返回袋鼠的版本。

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

访问看似是 Animal 的对象,但获得 Kangaroo 指定的行为,这正是多态性的本质——在期望其父对象的任何地方都可以替换子对象的能力。

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

于 2012-06-19T16:01:43.030 回答
1

现在如果我想调用 Animal 的 getLegs 方法,我该怎么做?是否可以?

如果你想访问被覆盖的方法——这与多态性相矛盾——你可以使用反射。从 的类中获取getLegs方法Animal,然后在您的袋鼠对象上调用它。然而,这是一个 hack,而不是你在常规程序中会做的事情。

SOP( Animal.class.getMethod("getLegs").invoke(a) );
于 2012-06-19T16:04:00.220 回答
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 Animal a = new Kangaroo();..因为没有人愿意这样做。而是他会直接写。Animal a = new Animal();..

所以最终决定调用哪个方法的是对象而不是引用

于 2012-06-19T16:18:33.827 回答