Python: Inheritance vs. Composition

I work with two classes in Python, one of which should be allowed to have any objects from the other class as children, while maintaining an inventory of these children as an attribute. Inheritance seemed the obvious choice for this parental <> child situation, but instead I became 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 

So basically, although it seems intuitively clear that Child () inherits from Parent (), deleting the inheritance doesn't change anything. The only advantage I can see for exiting Child (Parent), and not just for the Child () class, would be if I needed to add a lot more methods for the parent so that I wanted Child to inherit. Using self.parent = parent, I already have access to any additional attributes of the future parent.

Is there any other way to use pure inheritance and not pass the parent instance to the constructor (composition) of the Child?

+11
python inheritance composition
source share
2 answers

It is definitely not good to inherit a child from a parent or parent from a child.

The right way to do this is to create a base class, say, Person, and inherit both Child and Parent from it. The advantage of this is to remove code repetition, at the moment you only have the first and last name fields copied to both objects, but you can 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 to do this is to do it without inheritance, but to have only one Person object (against Parent and Child). The function of tracking the status of the family and parents / children can be transferred to another object.

The advantage of this approach is that you follow the principle of shared responsibility and make 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 
+20
source share

Firstly, 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 this behavior and extend it.

In your example, Child inherits two things from the parent. Constructor __init__ and havechild . You are redefining the constructor, and the havechild method havechild not work, since the list of children is not added. It also seems that you are not going to have children who have children.

Speaking, it seems you can really ask another question, for example, “Composition versus aggregation”. There is a design choice like Inheritance vs Composition, which may actually be especially interesting for Python, but it basically asks if you want to reuse the code by copying the behavior of the autonomous parent class (inheritance) or want to separate the different graphs of the class’s behavior ( due to the lack of a better word), and then create classes that are compositions of these granules.

take a look at that! In the book, the link is also well known and has a good catalog for different design templates.

0
source share

All Articles