Sometimes you will like to receive as argument a Parent reference and inside you probably want to do something specific of a child.
abstract class Animal{
public abstract void move();
}
class Shark extends Animal{
public void move(){
swim();
}
public void swim(){}
public void bite(){}
}
class Dog extends Animal{
public void move(){
run();
}
public void run(){}
public void bark(){}
}
...
void somethingSpecific(Animal animal){
// Here you don't know and may don't care which animal enters
animal.move(); // You can call parent methods but you can't call bark or bite.
if(animal instanceof Shark){
Shark shark = (Shark)animal;
shark.bite(); // Now you can call bite!
}
//doSomethingSharky(animal); // You cannot call this method.
}
...
In above's method you can pass either Shark or Dog, but what if you have something like this:
void doSomethingSharky(Shark shark){
//Here you cannot receive an Animal reference
}
That method can only be called by passing shark references
So if you have an Animal (and it is deeply a Shark) you can call it like this:
Animal animal...
doSomethingSharky((Shark) animal)
Bottom line, you can use Parent references and it is usually better when you don't care about the implementation of the parent and use casting to use the Child as an specific object, it will be exactly the same object, but your reference know it, if you don't cast it, your reference will point to the same object but cannot be sure what kind of Animal would it be, therefore will only allow you to call known methods.