intermediate

Inheritance and polymorphism

Use inheritance for true subtype relationships and polymorphism to call behavior through a shared contract without branching on concrete types.

Inheritance models is-a subtyping: `Square extends Rectangle` only if the subtype truly honors the parent contract (LSP). Polymorphism lets callers use a shared interface—`Notifier`—without branching on concrete classes; runtime dispatch invokes the right `send` implementation.

Prefer shallow hierarchies; deep trees couple unrelated changes and encourage override surprises.

On interviews: give a valid polymorphism example and a classic LSP violation (e.g., square-rectangle).

Common pitfalls: inheritance for code reuse only, overriding methods that break parent expectations, and `instanceof` chains instead of polymorphic calls.

The trade-off is concise shared behavior versus fragile subtype hierarchies—composition often wins.

Checklist:

  • Use inheritance for true subtyping.
  • Call through abstractions, not concrete types.
  • Check substitutability before extending.