Expert · Object-oriented programming · topic 37 of 50 · 30 min
Inheritance and composition
Explanation
Reusing a class
A company has employees. Managers are employees too: they have a name and a salary, but also a team and a bonus. Instead of copying the Employee code, we write a Manager class that inherits from Employee. The original class is called the parent (or base) class; the new one is the child (or subclass).
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
def yearly_pay(self):
return self.salary * 12
def describe(self):
return f"{self.name}, employee"
class Manager(Employee): # Manager inherits from Employee
def __init__(self, name, salary, team_size):
super().__init__(name, salary) # let the parent set name and salary
self.team_size = team_size
def describe(self): # override the parent's method
return f"{self.name}, manager of {self.team_size}"
e = Employee("Ravi", 40000)
m = Manager("Sunita", 90000, 6)
print(e.describe())
print(m.describe())
print(m.yearly_pay()) # inherited from Employee: 1080000super().__init__
super() gives you the parent class. Calling super().__init__(name, salary) runs the parent's setup code, so the child does not repeat it. Then the child adds its own extra attributes.
Overriding and extending
Overriding means the child defines a method with the same name as the parent. Python looks for a method on the child first, then on the parent. You can also extend a method: call the parent version with super() and add to its result.
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
def yearly_pay(self):
return self.salary * 12
class Manager(Employee):
def __init__(self, name, salary, bonus):
super().__init__(name, salary)
self.bonus = bonus
def yearly_pay(self):
return super().yearly_pay() + self.bonus # parent result + extra
print(Manager("Sunita", 90000, 100000).yearly_pay()) # 1180000isinstance: checking the type
class Employee: pass
class Manager(Employee): pass
m = Manager()
print(isinstance(m, Manager)) # True
print(isinstance(m, Employee)) # True: a Manager IS an Employee
print(isinstance(Employee(), Manager)) # False
print(issubclass(Manager, Employee)) # TrueComposition: "has a"
Inheritance is for "is a" relationships: a Manager is an Employee. When one thing only has another thing, use composition: store the other object as an attribute. A car has an engine; a car is not an engine.
class Engine:
def __init__(self, cc):
self.cc = cc
def start(self):
return f"{self.cc}cc engine started"
class Car:
def __init__(self, model, cc):
self.model = model
self.engine = Engine(cc) # a Car HAS an Engine
def start(self):
return f"{self.model}: " + self.engine.start()
print(Car("Swift", 1197).start())| Question | Answer | Use |
|---|---|---|
| Is a Manager an Employee? | Yes | Inheritance |
| Is a Car an Engine? | No, a Car has an Engine | Composition |
| Is a SavingsAccount a BankAccount? | Yes | Inheritance |
| Is an Order a list of items? | No, an Order has items | Composition |
Watch the lesson
Inheritance and composition · 1/6
In this lesson you will reuse classes with inheritance, and learn when to use composition instead.
Prefer a video by a teacher? Find free videos on “python inheritance super init tutorial” on YouTube ↗
In real life: Vehicles in a transport app
A city transport app shows buses, autos and metro trains. All of them have a number, a route and a fare() method, so they inherit from one Vehicle class. Each one overrides fare() with its own rule: a flat fare for the metro, per-kilometre for autos. Each vehicle also has a GPS tracker object (composition), because a bus is not a GPS tracker.
class Vehicle:
def __init__(self, number):
self.number = number
def fare(self, km):
return 0
class Auto(Vehicle):
def fare(self, km):
return 30 + 15 * max(0, km - 1.5)
class Metro(Vehicle):
def fare(self, km):
return 20 if km <= 5 else 40
for v in [Auto("MH12 AB 1234"), Metro("Line 3")]:
print(v.number, v.fare(6))Practice (0/3 done)
An Animal class is given. Write a class Dog that inherits from Animal and overrides speak() to return "Woof". Dog should still have the name attribute from Animal.
Employee is given. Write Manager(Employee) with __init__(self, name, salary, bonus) that calls super().__init__(name, salary) and stores bonus. Override yearly_pay() to return the parent's yearly pay plus the bonus.
Use composition. Engine is given. Write a class Car with __init__(self, model, cc) that stores model and creates self.engine = Engine(cc). Add a method start(self) that returns model + ": " + the engine's start() result.
Quick quiz
Read more (free)
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.