Suppose I have two classes: Animal and Dog. Dog is a subclass of Animal. I do the following code:
Animal a = new Dog();
Now I can call methods
If you are certain that it will always be a dog there is no reason for it. You might aswell use Dog d = new Dog(); as you described. But let's say you used a method instead of a constructor. The method returned an animal and you wouldn't know which implementation of animal you would get. You would still be able to use the same methods on the animal (even if it's a Dog, Elephant cat etc).
For extensibility purposes inheritance simplifies things. When you want to create an elephant or cat which also share some animal methods, You can easily get those by having animal as super class.
Normally the question you've asked is more similar to Inheritance vs Composition :) More "real life" example of why it's good to use polymorphism is for example usage of strategy design pattern. You can have many TaxPolicy implementation: UsaTaxPolicy, CanadaTaxPolicy, EuTaxPolicy, etc. If you have method calculateFinalPrice, which have to also calculate tax, then you inject the proper implementation and good calculation is executed, no matter you've passed Usa, Canada or Eu implementation.
Polymorphism allows you to write a method that works for any Animal
:
public void pet(Animal animal) {
...
}
This method would accept Dog
, Cat
, etc, including subclasses of Animal
that are yet to be written.
If the method were to take Dog
, it would not work for Cat
etc.
inheritance is the dynamic polymorphism. I mean when you remove inheritance you can not override anymore.
In Java, the concepts of polymorphism and inheritance are "welded together"; in general, it does not have to be that way:
There are languages where inheritance is decoupled from polymorphism:
virtual
)Going back to Java, the reason to use polymorphism is decoupling your code from the details of the implementation of its counter-parties: for example, if you can write a method Feed(Animal animal)
that works for all sorts of animals, the method would remain applicable when you add more subclasses or implementations of the Animal
. This is in contrast to a Feed(Dog dog)
method, that would be tightly coupled to dogs.
As far as the
Dog d = new Dog();
declaration goes, there is no general reason to avoid this if you know that the rest of your method deals specifically with dogs. However, in many cases the later is not the case: for example, your class or your methods would often be insensitive to the exact implementation, for example
List<Integer> numbers = new ArrayList<Integer>();
In cases like that, you can replace new ArrayList<Integer>()
with new LinkedList<Integer>()
, and know that your code is going to compile. In contrast, had your numbers
list been declared as ArrayList<Integer> numbers
, such switchover may not have been a certainty.
This is called "programming to an interface". There is a very good answer on Stack Overflow explaining it.
You can have other implementations of the Animal
class, such as Cat
. Then you can say
Animal a = new Dog();
Animal b = new Cat();
You can call methods of the Animal
class without caring which implementation it really is, and polymorphism will call the correct method. E.g.
a.speak(); // "Woof"
b.speak(); // "Meow"
Really, it's not "Polymorphism vs Inheritance" but "Polymorphism using Inheritance".