2

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?

Kevin Reid
  • 37,492
  • 13
  • 80
  • 108
chaosguru
  • 1,933
  • 4
  • 30
  • 44
  • You can't. That's the whole point of polymorphism. In Kangaroo you can do `super.getLegs()` but not from `main`. – Amir Raminfar Jun 19 '12 at 15:58
  • 4
    [According to Jon Skeet, you shouldn't.](http://stackoverflow.com/a/1032906/451590) – David B Jun 19 '12 at 15:58
  • The whole point of polymorphism is to access the most specialised method. – assylias Jun 19 '12 at 15:58
  • @Amir : But what If I need to get the Animal getLegs(); ? super.getLegs() I can always get but from animal Instance aint it possible? – chaosguru Jun 19 '12 at 15:59
  • Nope it is not possible from an instance. This violates polymorphism. All that is guaranteed is that there is a `getLegs` method. But not how it is implemented. As it should be. Why would you want to do this anyway? – Amir Raminfar Jun 19 '12 at 16:01
  • @AmirRaminfar Letting people call an implementation from a superclass on an object would not "violate polymorphism" as the call would not be intended as polymorphic, but it would severely violate encapsulation, because the fact that the base class must have an implementation of `getLegs` would get exposed to the outside world. – Sergey Kalinichenko Jun 19 '12 at 16:10
  • @chaosguru If you call super.getLegs(), which super class? That code needs to be in the subclass, as only a subclass has a single super class. That's fine, but why hide the super class implementation with a subclass implementation that only explicitly calls the super class? It might seem clever, but it is really just programming the computer to twiddle it's thumbs. Cutting out the code would have the same effect. Sometimes `super.getLegs()` should be in a subclass, but only when it modifies the super class value, Like a siamese twin subclass returning `super.getLegs()*2` – Edwin Buck Jun 19 '12 at 16:15
  • @EdwinBuck: Yes you are right! it sounds pratical – chaosguru Jun 20 '12 at 06:35

5 Answers5

3

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).

Edwin Buck
  • 69,361
  • 7
  • 100
  • 138
2

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.
Luca Geretti
  • 10,206
  • 7
  • 48
  • 58
1

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.

Paolo
  • 22,188
  • 6
  • 42
  • 49
1

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) );
Eran
  • 21,632
  • 6
  • 56
  • 89
1

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

Ahmad
  • 2,110
  • 5
  • 26
  • 36