Inheritance is NOT for code reuse, it is for substitution.
When thinking inheritance, code reuse is incidental.
A lot of developers think reusability when thinking inheritance but be aware, it's a wrong reasonning.
You should favor composition for code reusability over inheritance.
When you think substitution, then you can think inheritance.
A practical example to understand polymorphism is when you look at the design pattern named "Strategy".
Strategy allows to change algorithm at runtime without altering the orchestrator component.
For instance, imagine a video game when you manage some soldiers with evolving weapons.
Main algorithm (orchestrator algorithm) is about moving the soldier and hitting any enemy.
Level 1, you have a knife.
Level 2, you will have a gun.
Level 3, you will have a bomb.
Etc.
You don't want to explicitly deal with any kind of weapon within your main algorithm, you want a pseudo code like this inside let's say a class Soldier
:
hit() {
weapon.use(); // so generic !
}
instead of :
hit() {
if(weapon instance of Knife)
....
else if(weapon instance of Gun)
....
else if(weapon instance of Bomb)
....
// what if you create another weapon for a further level...you would have to alter this class to add another 'else if' clause, bad!
}
So to use the first way being the more concise and solid way, you will have to make usage of polymorphism, by subclassing Weapon
class with appropriate subclasses (Knife
, Gu
, Bomb
) implementing the use
method.
Polymorphism = weapon
can take several forms/structures/behaviors at runtime.
So in this case you are using composition
to change the used weapon at runtime, and you are using polymorphism to let the orchestrator ignorant of the exact weapon used.
It makes code flexible, robust, with easy maintenance.