Skip to main content

Keep the Promise

The Liskov Substitution Principle says: anywhere the code expects an interface, every class that implements it must work correctly. An implementation that technically fits but behaves badly — throws, does nothing, lies — breaks every function that trusted the interface.

An interface is a promise. fly() promises flying. A class that implements fly() by throwing an exception has signed a contract it cannot keep.


A Substitute That Breaks the Deal

The Bird interface promises fly(). Sparrows deliver. Penguins are birds too — so it feels natural to implement the interface... with a throw, because penguins cannot fly.

Now airShow, which works for every honest bird, crashes on a penguin. The bug is not in airShow — it is in the substitute that broke the promise.

The penguin that crashes the show

airShow trusts the interface and calls fly() on every bird. The sparrow performs; the penguin throws an exception and takes the whole show down (the try/catch only softens the landing to show the message).

Prompt
Write a PHP script showing a Liskov Substitution violation: a Bird interface with a fly method, a Sparrow that flies, and a Penguin whose fly throws a RuntimeException because penguins cannot fly. An airShow function calls fly on every bird; use try/catch to show the crash message when the penguin performs.
Output: PHP script

Separate the Promises

The fix: promise only what is true. Split the fat promise into Flyer and Swimmer. The sparrow implements Flyer, the penguin implements Swimmer — and no class signs a contract it cannot keep.

The best part is who catches the mistake now: airShow type-hints Flyer, so airShow(new Penguin()) fails the type check — PHP stops the call with a TypeError before any bird performs, and a static analyzer reports the line before the code even runs.

Every class keeps its promise

airShow accepts Flyer, poolShow accepts Swimmer. Each animal appears only where its promise holds — substitution is safe by construction.

Prompt
Fix the Liskov violation in PHP by splitting the promises: a Flyer interface with fly and a Swimmer interface with swim. Sparrow implements Flyer, Penguin implements Swimmer. Write airShow for flyers and poolShow for swimmers and run both, so every class only appears where its promise holds.
Output: PHP script
Every class keeps its promise

Any Flyer can join

The payoff of honest interfaces: a new Eagle joins the air show with no risk — anything that implements Flyer truly flies, so airShow never needs to doubt its input.

Prompt
Extend the PHP Flyer interface example with a new Eagle class and run an air show with several flyers, showing that any honest Flyer implementation can substitute safely.
Output: PHP script