Python中如何使用组合而不是继承

462 阅读2分钟

Python中的继承性很好,因为它促进了大量的代码重用。我们把共同的数据和行为放到基类中,然后在派生类中实现任何需要的额外数据和行为。因此,当使用继承时,你是在利用 "是 "的关系。例如,"汽车 "就是 "车辆"。在Python中使用面向对象的编程风格时,代码重用的另一种方法是组合。组合有一种不同的方法,其中使用了 "是 "的关系。基本上在组合中,你从更简单的对象中组装复杂的对象。你从其他对象中构建对象。例如,你可以建立一个汽车对象,它有一个引擎对象,或者有一个轮胎对象,等等。我们将在本课中看看如何使用组合而不是继承。


继承与组合

黄线的左边是一个[继承的]例子,从概念上看是这样的。右边是一个组合的例子。

Inheritance vs Composition


代码中的组合

在下面的代码中,我们使用了组合。你会注意到,在定义的任何一个类中都没有继承性。然而,我们看到的是实例化一个引擎对象的方法,然后将该对象分配给拖拉机对象的一个属性。所以你看,这是一个从一个更简单的类中建立一个更复杂的类的例子。这就是行动中的组合。

# Using composition to build complex objects
class Tractor():
    def __init__(self, model, make, engine=None):
        self.model = model
        self.make = make

        # Use references to other objects, like Engine and Implement
        self.engine = engine
        self.implements = []

    def addimplement(self, implement):
        self.implements.append(implement)

    def get_tractor_implements(self):
        return self.implements


class Engine():
    def __init__(self, cylinders, horsepower):
        self.cylinders = cylinders
        self.horsepower = horsepower

    def __str__(self):
        return f"{self.cylinders} cylinder {self.horsepower} horsepower"


class Implement():
    def __init__(self, attachment_type):
        self.attachment_type = attachment_type


engine1 = Engine(3, 25)
tractor1 = Tractor("John Deere", "1025R", engine1)

tractor1.addimplement(Implement("Loader"))
tractor1.addimplement(Implement("Backhoe"))
tractor1.addimplement(Implement("Mowing Deck"))
tractor1.addimplement(Implement("Snowblower"))

print(f"This is a {tractor1.model} tractor.")
print(f"It has {tractor1.engine} engine.")
attachments = tractor1.get_tractor_implements()
print("The attachments it has include: ")
for attachment in attachments:
    print(" - " + attachment.attachment_type)
This is a John Deere tractor.
It has 3 cylinder 25 horsepower engine.
The attachments it has include:
 - Loader
 - Backhoe
 - Mowing Deck
 - Snowblower