i have been reading about composition in python and after following some articles and answers here on stackoverlow i think i am able to get what it is and how it is implemented. but one question to which i am unable to find answer is why composition? (not comparing with benefits over inheritance). here is an example that i got from here:
class Salary:
def __init__(self,pay):
self.pay=pay
def get_total(self):
return (self.pay*12)
class Employee:
def __init__(self,pay,bonus):
self.pay=pay
self.bonus=bonus
self.obj_salary=Salary(self.pay)
def annual_salary(self):
return "Total: " + str(self.obj_salary.get_total()+self.bonus)
obj_emp=Employee(100,10)
print (obj_emp.annual_salary())
i would like to understand with a little realistic example where it would benefit by seperating two related classes( and what benefits exactly?)
using an extended version of your example
class Salary:
def __init__(self,pay):
self.pay=pay
def get_total(self):
return (self.pay*12)
def increase(self):
self.pay *= 1.1
class Employee:
def __init__(self,pay,bonus):
self.pay=pay
self.bonus=bonus
self.obj_salary=Salary(self.pay)
def annual_salary(self):
return "Total: " + str(self.obj_salary.get_total()+self.bonus)
obj_emp=Employee(100,10)
print (obj_emp.annual_salary())
calling employee.salary.increase makes much more sense than employee.increase
Also what if you needed multiple objects? would you inherit one of them or all of them leading to name possible name clashes?
class Game:
def __init__(self):
self.screens = [LoadingScreen, MapScreen]
self.player = Player()
self.display = Display()
self.stats = Stats(self.display)
self.screenIndex = self.player.getScreen()
self.currentScreen = self.screens[self.screenIndex]()
self.run()
* EDIT * after looking at this
but on looking it up again i find that increase could be renamed to increaseSalary so employee.increaseSalary() would make sense right?
you could simply move the increase to the employee class but what if you had a Manager class or a Boss class you would need to repeat the same code for each class
class Employee:
def __init__(self,pay,bonus):
self.pay=pay
self.bonus=bonus
def annual_salary(self):
return "Total: " + str(self.obj_salary.get_total()+self.bonus)
def increase_salary(self):
self.pay *= 1.1
class Manager:
def __init__(self,pay,bonus):
self.pay=pay
self.bonus=bonus
def annual_salary(self):
return "Total: " + str(self.obj_salary.get_total()+self.bonus)
def increase_salary(self):
self.pay *= 1.1
class Boss:
def __init__(self,pay,bonus):
self.pay=pay
self.bonus=bonus
def annual_salary(self):
return "Total: " + str(self.obj_salary.get_total()+self.bonus)
def increase_salary(self):
self.pay *= 1.1
OR only once
class Salary:
def __init__(self,pay):
self.pay=pay
def get_total(self):
return (self.pay*12)
def increase(self, addition):
self.pay *= addition
you could also use a class methods to find average, max, min etc a lot easier