2

我一直在阅读有关 python 中的组合的内容,并且在 stackoverlow 上关注了一些文章和答案之后,我想我能够了解它是什么以及它是如何实现的。但我无法找到答案的一个问题是为什么要作曲?(不与继承的利益进行比较)。这是我从这里得到的一个例子:

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

我想用一个现实的例子来理解,通过分离两个相关的类会受益(以及究竟有什么好处?

4

2 回答 2

4

使用您的示例的扩展版本

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

调用employee.salary.increase 比调用employee.increase 更有意义

另外,如果您需要多个对象怎么办?您会继承其中一个还是全部继承导致可能的名称冲突?

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

* 编辑 * 看完这个

but on looking it up again i find that increase could be renamed to increaseSalary so employee.increaseSalary() would make sense right?

您可以简单地将增加的内容移至员工类,但如果您有经理类或老板类,您需要为每个类重复相同的代码

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

或者只有一次

class Salary:
    def __init__(self,pay):
        self.pay=pay

    def get_total(self):
       return (self.pay*12)

    def increase(self, addition):
        self.pay *= addition

您还可以使用类方法更容易地找到平均值、最大值、最小值等

于 2017-06-21T15:42:24.450 回答
0

好的,即使我是菜鸟,我也会尝试一下。也可能有一些我遗漏的观点,但这是我喜欢思考的方式,任何人,答案:

因为它为您提供了很大的灵活性并允许您将不一定具有父/子关系的对象“组合”在一起(在经典 OOP 中称为 IS-A 类型继承)

例如说你有一rifle堂课。你想添加(或撰写)attachments它。

你将如何通过继承来做到这一点?它不会很灵活。

所以你可以做的就是将你的附件定义为有自己的类,比如 asight和一个muzzle break类,然后将这些附件类的实例声明为你的rifle类和 BAM 中的字段,你现在可以访问在sightand中定义的方法muzzle break,就像使用继承子类可以访问其超类方法。

无论如何要继续,你可以从这个例子中看到现在创建各种武器类是多么容易,比如 a howitzer,如果做得好,你可以声明sightmuzzle breakin 的实例howitzer

请注意,我们创建的关系层次结构是完全平坦的。

要使用继承完成所有这些,您将定义一个基类,例如 使用和weapon中定义的相同方法。然后,您将创建分支到和 to 的子类。sightmuzzle breakriflehowitzer

现在想象一下,您不想rifle拥有 a sightbut a scope。你必须在你的基类中经历所有这些圈套和恶作剧才能实现这一点。

使用组合,您只需创建一个新类scope(实际上可以从 继承sight),删除sightfrom的实例rifle并插入scope. 请注意,没有对howitzer.

尽管如此,我仍然认为继承是一种在适当情况下可以利用的有用工具,就像组合一样。

于 2017-06-21T15:55:24.033 回答