Other Answers discus the theory, this is an example to show why dynamic dispatch (also called late binding) is needed.
Assume you have an Class 'Rectangle`.
public class Rectangle{
public void draw() {
System.out.println("___\n| |\n---");
//does it look nice?
}
}
And you have a subclass with rounded corners
public class RoundedRectangle extends Rectangle {
@Override
public void draw() {
System.out.println("assume it is a rectangle with rounded corners");
}
}
Now assume you have a method getting with an Parameter of Type Rectangle, which is used in the method to invoke the draw method
public class Demo() {
...
public demonstration(Rectangle rect) {
rect.draw();
}
...
}
It the argument of this method is of class Rectangle then it will draw
___
| |
---
But when the argument is of type RoundedRectangle, then we expect:
assume it is a rectangle with rounded corners
And this is where late binding is needed for: When the code compiles, it is not clear which method needs to be invoked by
rect.draw();
I could be Rectangle.draw(), RoundedRectangle.draw(), or the draw method of any other yet not implemented subclass of Rectangle.
Summary (from the view of an developer):
So late binding means: invoke the method of given signature (Method name, and argument list) for an instance where is only known that it is of an specific class or subclass - but it is not known which class it is exactly. And when a method is overriden, then ivoke the overriding method.
So there is no Polymorphism vs. Late Binding -- It is you need Late Binding when you have Polymorphism. In Java and in C++ (and i belive, in every other Object Oriented language too)