Say you have the following (simplified):
Airplane plane = new MyAirplane();
Then you do all sorts of things with it:
List<Airplane> formation = ...
// superclass is important especially if working with collections
formation.add(plane);
// ...
plane.flyStraight();
plane.crashTest();
// ... insert some other thousand lines of code that use plane
Thing is. When you suddenly decide to change your plane to
Airplane plane = new PterdodactylSuperJet();
all your other code I wrote above will just work (differently, of course) because the other code relies on the interface (read:public methods) provided by the general Airplane
class, and not from the actual implementation you provide at the beginning. In this way, you can pass on different implementations without altering your other code.
If you hadn't used an Airplane
superclass and just written MyAirplane
and PterdodactylSuperJet
in the sense that you replace
MyAriplane plane = new MyAirplane();
with
PterdodactylSuperJet plane = new PterdodactylSuperJet();
then you have a point: the rest of your code may still work. But that just happens to work, because you wrote the same interface (public methods) in both classes, on purpose. Should you (or some other dev) change the interface in one class, moving back and forth between airplane classes will render your code unusable.
Edit
By on purpose I mean that you specifically implement methods with the same signatures in both MyAirplane
and PterodactylSuperJet
in order for your code to run correctly with both. If you or someone else change the interface of one class, your flexibility is broken.
Example. Say you don't have the Airplane
superclass and another unsuspecting dev modifies the method
public void flyStraight()
in MyAirplane
to
public void flyStraight (int speed)
and assume your plane
variable is of type MyAirplane
. Then the big code would need some modifications; assume that's needed anyway. Thing is, if you move back to a PterodactylSuperJet
(e.g. to test it, compare it, a plethora of reasons), your code won't run. Whygodwhy. Because you need to provide PterodactylSuperJet
with the method flyStraight(int speed)
you didn't write. You can do that, you can repair, that's alright.
That's an easy scenario. But what if
- This problem bites you in the ass a year after the innocent modification? You might even forget why you did that in the first place.
- Not one, but a ton of modificatios had occurred that you can't keep track of? Even if you can keep track, you need to get the new class up to speed. Almost never easy and definitely never pleasant.
- Instead of two plane classes you have a hundred?
- Any linear (or not) combination of the above?
If you had written an Airplane
superclass and made each subclass override its relevant methods, then by changing flyStraight()
to flyStraight(int)
in Airplane
you would be compelled to adapt all subclasses accordingly, thus keeping consistency. Flexibility will therefore not be altered.
End edit
That's why a superclass stays as some kind of "daddy" in the sense that if someone modifies its interface, all subclasses will follow, hence your code will be more flexible.