Inheritance
A subclass reuses and extends a superclass. It models 'is-a' relationships — and creates the tightest coupling in OOP.
Level: intermediate
What is it?
Inheritance lets a class (the subclass) acquire the fields and methods of another (the superclass), and add or override behavior. It models an 'is-a' relationship: a Dog is an Animal. Method lookup walks up the chain until a definition is found, and super lets a subclass call the parent's version.
Why does it matter?
It removes duplication among closely related types and enables polymorphism: code written for Animal works for every subclass. It is also the strongest coupling in OOP, so knowing its limits is as important as knowing how to use it.
Mental model
A family recipe passed down with modifications. The child kitchen starts with the parent's recipe, changes the spice, and leaves everything else alone. If the parent changes the recipe, every child's dish changes too.
How it works
- 'is-a' test: use inheritance only if every instance of the subclass really is an instance of the superclass, in all contexts.
- Overriding replaces behavior; calling super preserves the parent's part.
- Subclasses depend on superclass internals, so a change to the parent can break every child (the fragile base class problem).
- Single inheritance (Java) is simpler; multiple inheritance (C++, Python) needs rules for resolving conflicts, like Python's MRO.
- Deep hierarchies are hard to read. Keep them shallow, and prefer composition when unsure.
Steps
- Define the base class
- Subclass and extend
- Override where behavior differs
- Call through a base-typed reference
- Lookup finds the most specific method
Code example: Subclasses override one method
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "..."
class Dog(Animal):
def speak(self):
return "Woof"
class Cat(Animal):
def speak(self):
return "Meow"
for a in (Dog("Rex"), Cat("Tom"), Animal("Thing")):
print(a.name, a.speak()) # Rex Woof / Tom Meow / Thing ...Real-world usage
- Framework extension points (subclass a base controller, view, or test case)
- Exception hierarchies
- Closely related types that share most of their behavior
Common mistakes
- Inheriting to reuse code when the relationship is not 'is-a'.
- Overriding a method in a way that breaks the base class's contract.
- Building hierarchies five levels deep.
Interview questions
What is the 'is-a' test?
Ask whether every instance of the subclass can stand in for the superclass everywhere. If not (a Square that cannot honor Rectangle's independent width and height), inheritance is the wrong tool.
What is the fragile base class problem?
Subclasses depend on the parent's implementation, so an apparently safe change in the parent can break the subclasses. It is a reason to prefer composition or to design classes explicitly for inheritance.
How does Python resolve methods with multiple inheritance?
It uses the method resolution order (MRO), computed by C3 linearization, so each class appears once and a class always precedes its parents. ClassName.__mro__ shows it.