简体   繁体   中英

Is this still polymorphism?

While coding, I got an interesting doubt about polymorphism and I couldn't understand a solution for this.

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
  }
}

Now If I want to call the getLegs method of Animal , how do I? Is it possible? Is it still polymorphism?

Yes, it is the most basic form of demonstrating polymorphisim.

Basically you are dealing with an Animal named a . When you call a.getLegs() your code doesn't bind to the implementation of getLegs() in Animal , rather it binds to the lowest sub-class implementation, getLegs() in Kangraoo() .

If the Animal has an implementation, it is said to be hidden by the subclass implementation. If Animal has no implementation, then it is not possible to construct stand-alone classes of Animal as they lack implementations for all of the required methods, and under such a circumstance, Animal is said to be an abstract class (one that cannot be constructed directly, but only can be constructed by it's sub classes).

If you really want to call your method for Animal, and you can employ a static method, you can use hiding instead of overriding.

It works as follows: for static methods only, the called method is the one related to the declared type , not the object instance. In other words, it follows the class because the method is a class method, not an instance method.

An example, adapted from 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();
  }
}

The result will be (pay attention to the 3rd and 4th lines, as opposed to the 1st and 2nd):

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

In Java it's not possible to access Animal's implementation. It will always return Kangaroo's version.

(Note in C# it is possible by tagging the overriding method with "new", but it's a fairly specialised use case).

Accessing what appears to be an Animal but getting the behaviour specified by Kangaroo is exactly what polymorphism is - the ability for a child object to be substituted wherever its parent is expected.

In general you wouldn't want to have the calling code know about the inheritance hierarchy because this would tightly couple your code together. If you genuinely need to access Animal's implementation of this method it suggests your design is probably wrong.

Now If I want to call the getLegs method of Animal, how do I? Is it possible?

If you want to access the overridden method - which contradicts polymorphism - you can use reflection. Get the getLegs method from Animal 's class, and then invoke it on your Kangaroo object. However, this is a hack, and not something you'd do in a regular program.

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

The spirit of Polymorphism is to execute different code decided at runtime. To make it more clear, I'll modify your code a bit.

    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

  }
}

and Yes, as all say you can't call Animal from your line Animal a = new Kangaroo(); ..as none will want to do it. Rather he will directly write. Animal a = new Animal(); ..

So finally it is the object not referance which decides which method will be called

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM