Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parent methods which return child class instances

Tags:

python

oop

class

Is it bad practice, and if so, why, to return instances of child classes as output of methods of an instance of the parent class?

For example, can the following --

class Parent(object):
    def __init__(self, attr):
        self.attr = attr

    def child(self, typ):
        if typ == 'a':
            return ChildA(self.attr)
        else:
            return ChildB(self.attr)

class ChildA(Parent):
    pass

class ChildB(Parent):
    pass

be a good design?

like image 457
Bach Avatar asked Sep 30 '22 19:09

Bach


1 Answers

I would appreciate if someone more knowledgeable answers this question, but as this has yet to happen, I'll throw in my two cents' worth.


I think that it's indeed not good practice. Parent classes shouldn't directly reference child classes for a number of reasons:

  • First and foremost, it impedes future extensions of the module. Whenever a new child class is introduced, it would probably require updating the parent class as well in order to take this new child class into account in its implementation. This breaks the open-closed principle of the SOLID principles of object-oriented programming.

  • Another drawback, at least in Python, is that it forces all child classes to be defined in the same file, in order to avoid circular imports.

  • Furthermore, since the specified method is inherited by the child classes, then unless it's overridden, it triggers some kind of familiarity between "brother" classes, which might not be desired.

Although the technical issues may be circumvented with some coding effort, this approach unnecessarily places another burden on the programmer.

I'm sure that there are certain situations where it would seem useful for a parent class to be made aware of its child classes, however I think that in general, such situations infer an error in design and an alternative solution that doesn't involve this kind of introspection should be sought after.

Note that this doesn't mean parent objects shouldn't utilize child objects. Child objects, like all other objects, may be legitimately received as arguments or returned by their parent's methods. The parent's methods may even treat them as ordinary parent objects since a child object is also a parent object and that's one of the main pillars of object-oriented programming.


Regarding your particular example, consider the factory design pattern. For example:

class Parent(object):
    def __init__(self, attr):
        self.attr = attr

class ChildA(Parent):
    pass

class ChildB(Parent):
    pass

class Factory(object):
    def __init__(self, parent):
        self.parent = parent

    def create(self, <some_external_data>):
        if <an algorithm that determines the desired type based
            on some_external_data and the state of the parent>:
            return ChildA(parent.attr)
        else:
            return ChildB(parent.attr)
like image 108
Yoel Avatar answered Oct 03 '22 01:10

Yoel