Skip to content

OOP: favour composition over inheritance

Your classes inherit from each other over several levels and every new feature forces yet another subclass.

Best practiceIntermediateObject-oriented programmingTypeScriptPHPPython
interface Channel {  send(to: string, message: string): Promise<void>;}class SmsChannel implements Channel {  async send(to: string, message: string) { /* API SMS */ }}class Notifier {  constructor(private channels: Channel[]) {}  async notify(to: string, message: string) {    await Promise.all(this.channels.map((c) => c.send(to, message)));  }}// On assemble les comportements au lieu d'empiler des sous-classesconst notifier = new Notifier([new SmsChannel(), new EmailChannel()]);

Explanation

With inheritance, you quickly end up with classes like SmsAndEmailNotifierWithLogging. Composition means assembling small interchangeable objects that share the same contract (an interface).

  • Adding a channel (WhatsApp, push…) means writing a new class without touching Notifier.

  • Testing becomes easy: pass a fake channel to Notifier.

  • Changing behaviour at runtime is possible: the channel list can come from configuration.

Inheritance remains useful for a genuine, stable "is a" relationship (a Dog is an Animal). To share behaviour, prefer "has a".

Share