Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

a realistic usage of composition in python

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?)

like image 748
anekix Avatar asked Oct 12 '25 09:10

anekix


1 Answers

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

like image 92
Joshua Nixon Avatar answered Oct 14 '25 23:10

Joshua Nixon