Design Principle:
Program to an interface and NOT to an implementation.
Here interface means super type. It can be an interface as well as abstract class. The point is take advantage of
polymorphism and make sure that runtime object isn't hard-coded into your code.
First I will give a little description about the above classes.
We have two classes(Dog and Cat) which implements Animal interface. These are called "Behavioral classes" because their sole purpose of living is to produce sound. CallAnimal class helps us to invoke the makeSound() method of the "Behavioral classes" at run time.
Note:
It will be nice if you package the implementation classes and CallAnimal and jar it. Now the animal package can be shipped anywhere.
Runtime object isn't hard-coded into your code.
What do I mean by this. Image if you hard-coded CallAnimal class's getAnimal like
public void getAnimal(Dog animal) { }
This will NOT allow you to call the Cat class which also implements Animal interface.
So only I said program to an interface(super type)(Animal) and NOT to an implementation(Dog).
Instead of having a class like CallAnimal we could have hard-coded the instantiation of the sub-types like
Dog dog = new Dog();
dog.makeSound();
But hard-coding the instantiation of the sub-type Object doesn't help you to take advantage of polymorphism.
Always assign the implementation object at runtime.