Python: Inheritance versus Composition

前端 未结 2 2079
轮回少年
轮回少年 2020-12-01 11:26

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 childre

相关标签:
2条回答
  • 2020-12-01 11:35

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

    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.

    Here is an example:

    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(Child, self).__init__(firstname, parent.lastname)
            self.parent = parent
    

    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.

    Here is an example:

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

    It works like this:

    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
    
    0 讨论(0)
  • 2020-12-01 11:56

    First off, I think you are confusing things. As you yourself mention inheritance is used in a class that wants to inherit the nature of the parent class and then modify that behavior and extend it.

    In your example Child inherits two things from Parent. The constructor __init__ and havechild. You are overriding the constructor and the havechild method shouldn't work, since there is no kids member list to append the new child to. Also it appears that you are not intending to have the children have children.

    That being said it seems you may actually want to ask a different question, such as Composition vs Aggregation. There is such a design choice as Inheritance vs Composition which actually may be particularly interesting for Python, but it mainly asks whether you want to reuse code by copying the behavior of a standalone parent class (inheritance) or you want to separate different class behavior granules (for lack of better word) and then create classes which are compositions of these granules.

    have a look at this! The book referenced is also well known and has a good catalogue for different design patterns.

    0 讨论(0)
提交回复
热议问题