Python:继承与组合 [英] Python: Inheritance versus Composition

查看:142
本文介绍了Python:继承与组合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Python中的两个类,其中一个应该被允许将来自另一个类的任何数字对象作为子项,同时将这些子项的清单作为属性保存。继承似乎是这个父母<>孩子情况的明显选择,而是我所得到的是一个组合的例子。以下是简化代码:

I am working with two classes in Python, one of which should be allowed to have any number objects from another class as children while keeping an inventory of these children as an attribute. Inheritance seemed like the obvious choice for this parent<>child situation but instead what I have arrived at is an example of composition. Here is the simplified code:


class Parent():

    def __init__(self,firstname,lastname):
        self.firstname = firstname
        self.lastname = lastname
        self.kids = []

    def havechild(self,firstname):
        print self.firstname,"is having a child"
        self.kids.append(Child(self,firstname))

class Child(Parent):

    def __init__(self,parent,firstname):
        self.parent = parent
        self.firstname = firstname
        self.lastname = parent.lastname

所以基本上,虽然让Child()从Parent()继承,删除继承似乎没有直观意义,但是改变一切。我可以看到离开 Child(Parent)而不仅仅是 class Child()的唯一好处是,如果我需要向 Parent <添加更多方法/ em>我希望 Child 继承。使用 self.parent = parent ,我已经可以访问Parent的任何其他未来属性。

So basically, while it seems to make intuitive sense to have Child() inherit from Parent(), removing the inheritance, does not change anything at all. The only benefit I can see for leaving Child(Parent) instead of just class Child() would be if I needed to add a lot more methods to Parent that I would like Child to inherit. Using the self.parent = parent, I already have access to any additional future attributes of the Parent.

还有其他方法可以使用pure继承而不是将 Parent 实例传递给 Child 构造函数(组合)?

Is there another way to use pure inheritance rather than passing the Parent instance into the Child constructor (composition)?

推荐答案

继承子女的父母或子女的父母是绝对不好的。

It is definitely not good to inherint Child from Parent or Parent from Child.

正确的做法是创建基类,让我们说人并从中继承Child和Parent。
执行此操作的一个优点是删除代码重复,此时您只将firstname / lastname字段复制到两个对象中,但您可能有更多数据或其他方法,例如 get_name() 使用此数据。

The correct way to do it is to make a base class, let's say Person and inherit both Child and Parent from it. An advantage of doing this is to remove code repetition, at the moment you have only firstname / lastname fields copied into both objects, but you may have more data or additional methods, like get_name() to work with this data.

以下是一个示例:

class Person(object):

    def __init__(self, firstname, lastname):
        self.firstname = firstname
        self.lastname = lastname

    def get_name(self):
        return '%s %s' % (self.firstname, self.lastname)


class Parent(Person):

    def __init__(self, firstname, lastname):
        super(Parent, self).__init__(firstname, lastname)
        self.kids = []

    def havechild(self, firstname):
        print self.firstname, "is having a child"
        self.kids.append(Child(self, firstname))


class Child(Person):

    def __init__(self, parent, firstname):
        super(Parent, self).__init__(firstname, parent.lastname)
        self.parent = parent

另一种方法是在没有继承的情况下执行此操作,但只有一个Person对象(vs Parent和Child)。
跟踪家庭状态和父母/子女的功能可以移动到另一个对象。

Another way of doing this is to do it without inheritance, but only have one Person object (vs Parent and Child). The feature of tracking family status and parents / children can be moved into another object.

这种方法的一个优点是你遵循单一责任原则并保持对象简单,每个对象只做一件事。

An advantage of this approach is that you follow the single responsibility principle and keep objects simple, each object does only one thing.

以下是一个示例:

from collections import defaultdict

class Person(object):

    def __init__(self, firstname, lastname):
        self.firstname = firstname
        self.lastname = lastname

    def get_name(self):
        return '%s %s' % (self.firstname, self.lastname)


class FamilyRegistry(object):

    def __init__(self):
        self.kids = defaultdict(list)

    def register_birth(self, parent, child_name):
        print parent.firstname, "is having a child"
        child = Person(child_name, parent.lastname)
        self.kids[parent.lastname].append(child)
        return child

    def print_children(self, person):
        children = self.kids[person.lastname]
        if len(children) == 0:
            print '%s has no children' % person.get_name()
            return
        for child in children:
            print child.get_name()

它的工作原理如下:

joe = Person('Joe', 'Black')
jill = Person('Jill', 'White')
registry = FamilyRegistry()
registry.register_birth(joe, 'Joe Junior') # Joe is having a child
registry.register_birth(joe, 'Tina')       # Joe is having a child
registry.print_children(joe)               # Joe Junior Black
                                           # Tina Black
registry.print_children(jill)              # Jill White has no children

这篇关于Python:继承与组合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆