Composition vs Inheritance
"Favor composition over inheritance." Inheritance is an is-a relationship; composition is a has-a relationship. Composition is more flexible and easier to test.
Inheritance (is-a)
class Animal:
def breathe(self): return "breathing"
class Dog(Animal): # Dog IS AN Animal
def bark(self): return "Woof!"
# Works, but creates tight coupling.
# Changes to Animal affect all subclasses.Composition (has-a)
class Engine:
def __init__(self, horsepower):
self.hp = horsepower
def start(self):
return f"Engine started ({self.hp}hp)"
class GPS:
def navigate(self, dest):
return f"Navigating to {dest}"
class Car: # Car HAS AN Engine and a GPS
def __init__(self, make, hp):
self.make = make
self.engine = Engine(hp)
self.gps = GPS()
def start(self):
return f"{self.make}: {self.engine.start()}"
def navigate(self, dest):
return self.gps.navigate(dest)
car = Car("Toyota", 150)
print(car.start())
print(car.navigate("Airport"))Combining Both
class Logger:
def log(self, msg): print(f"[LOG] {msg}")
class UserService:
def __init__(self):
self.logger = Logger() # composition
def create_user(self, name):
self.logger.log(f"Creating user: {name}")
return {"name": name, "id": id(name)}