Question presented to candidate: "People say 'favour composition over inheritance'. What is the difference between the two, can you show it in Python, and when is inheritance still the right choice?"
What a strong answer should cover:
- Inheritance is an is-a relationship: the subclass gets every attribute and method of the base and can be used wherever the base is expected (substitutability)
- Composition is a has-a relationship: the object holds other objects as attributes and calls them, exposing only its own interface
- Why composition is often preferred: looser coupling, no fragile base class, parts can be swapped at runtime and replaced by fakes in tests, no subclass explosion when features combine
- A concrete Python trap: subclassing
dictand overriding__setitem__is bypassed bydict.__init__andupdate();collections.UserDict(which wraps a dict) fixes it - When inheritance fits: a real is-a relationship, framework base classes and ABCs, small mixins; delegation with
__getattr__as a middle ground
Clarifying questions expected:
- Is the new type genuinely a kind of the old one, usable everywhere the old one is?
- Will behaviours need to be combined or swapped (formats, storage, transports)?
Code / implementation expected: Optional β the same feature built both ways, for example a Stack that inherits from list versus one that holds a list.