返回子类实例的父方法

Bac*_*ach 5 python oop class

返回子类的实例作为父类实例的方法的输出是不是不好的做法?如果是,为什么?

例如,可以如下——

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
Run Code Online (Sandbox Code Playgroud)

是一个好的设计吗?

Yoe*_*oel 5

如果有更有知识的人回答这个问题,我将不胜感激,但由于这还没有发生,我将投入我的两美分。


我认为这确实不是一个好的做法。出于多种原因,父类不应直接引用子类:

  • 首先,它阻碍了模块的未来扩展。每当引入新的子类时,可能还需要更新父类,以便在其实现中考虑到这个新的子类。这打破了面向对象编程的SOLID原则开闭原则

  • 另一个缺点,至少在Python中,是它强制所有子类在同一个文件中定义,以避免循环导入。

  • 此外,由于指定的方法是由子类继承的,因此除非重写它,否则它会触发“兄弟”类之间的某种熟悉性,这可能是不希望的。

尽管可以通过一些编码工作来规避技术问题,但这种方法不必要地给程序员带来了另一个负担。

我确信在某些情况下,父类了解其子类似乎很有用,但是我认为一般来说,这种情况会推断出设计中的错误以及不涉及的替代解决方案应该寻求这种内省。

请注意,这并不意味着父对象不应使用子对象。子对象与所有其他对象一样,可以合法地作为参数接收或由其父对象的方法返回。父对象的方法甚至可以将它们视为普通的父对象,因为子对象也是父对象,并且这是面向对象编程的主要支柱之一。


关于您的特定示例,请考虑工厂设计模式。例如:

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)
Run Code Online (Sandbox Code Playgroud)