Exercise: Liskov Substitution
This exercise puts the Liskov Substitution Principle into code.
Scenario
Model a small bird registry that demonstrates LSP through its hierarchy. The base class Bird
promises a move() operation. Flying birds — sparrows and eagles — implement move() by
flying. Flightless birds — penguins — implement move() by walking. No subtype throws or
no-ops: every subtype is a valid substitute for Bird at the move() call site.
Commands
The program reads a list of commands, one per line, and prints one line of output per command.
| Command | Behavior | Output |
|---|---|---|
["add", type, name] | Create a bird of the given type | "Added <name>" if type is sparrow, eagle, or penguin; "Unknown type: <type>" otherwise |
["move", name] | Call move() on the named bird | "<name> flies" for flying birds; "<name> walks" for flightless birds; "<name> not found" if no such bird exists |
["count"] | Count successfully added birds | "Birds: <n>" |
7 add sparrow Tweety add penguin Tux add eagle Bald move Tweety move Tux move Bald move Ghost
Added Tweety Added Tux Added Bald Tweety flies Tux walks Bald flies Ghost not found
Your task
Create the bird hierarchy the dispatcher uses: FlyingBird and FlightlessBird (both extend Bird and implement move()), then Sparrow and Eagle (extend FlyingBird) and Penguin (extends FlightlessBird). The dispatcher below already calls new Sparrow(name), new Eagle(name), and new Penguin(name) by name, so the code tells you exactly what to build.