【问题标题】:Load child class from base class从基类加载子类
【发布时间】:2018-01-08 11:15:19
【问题描述】:

我有一个基类BaseClass 和多个子类SubClass1SubClass2。实际上,该程序仅适用于其中一个子类的实例。子类使用save 方法实现接口。加载保存的元素时,您不知道要加载的类。因此,我正在考虑在基类中使用 load 方法,但这提出了一个问题:如何从基类中的子类之一实例化元素?

For clarity, here is some simple code:

    class BaseClass:
        def load(self):
            #load element of subclass
            return subclass_element

    class myInterface:
        __metaclass__ = ABCMeta
        @abstractmethod
        def save(self):
            raise NotImplementedError

    class SubClass1(BaseClass, myInterface):
        def save(self):
            #save the element

    class SubClass2(BaseClass, myInterface):
        def save(self):
            #save the element

我也愿意接受任何支持不同设计的建议。我不确定我没有实施反模式。

编辑 1:添加工厂类

根据我对@Vishal_Raja 和@Gholamali-Irani 建议的理解:

class SubClassLoader: #this is our factory class
    registered_subclasses = {} #static dict of subclasses

    @StaticMethod
    def register(classname, class):
        SubClassLoader.registered_subclasses[classname] = class

    @StaticMethod
    def get_instance(filepath):
        classname, arguments = get_classname(filepath) 
        if classname in SubClassLoader.registered_subclasses:
            return SubClassLoader.registered_subclasses[classname](arguments)
        else:
            raise TypeError("Unknown class %s" % classname)


class BaseClass:
    pass


class myInterface:
    __metaclass__ = ABCMeta
    @abstractmethod
    def save(self):
        raise NotImplementedError


class SubClass1(BaseClass, myInterface):
    def save(self):
        #save the element


class SubClass2(BaseClass, myInterface):
    def save(self):
        #save the element

【问题讨论】:

  • 这是关于一般的 OOP,还是专门针对 Python?
  • Python 上下文中的通用 OOP
  • 但主要是一般的OOP

标签: oop inheritance design-patterns


【解决方案1】:

首先:在父子之间建立依赖关系是糟糕的设计。继承(来自父母的孩子)是一种依赖。如果您从父级到子级添加另一个依赖项,则会产生循环依赖项,并且很难维护和扩展。

在面向对象的启发式设计中,我们有:

启发式 5.1:派生类必须根据定义了解其基类, 但是基类不应该知道它们的派生类。

为什么?

如果基类知道它们的派生类,那么它是 暗示如果将新的派生类添加到基类中,则代码 基类的需要修改。这是一个不受欢迎的 在基础和派生中捕获的抽象之间的依赖关系 类。我们将看到针对这些类型的更好的解决方案 当我们稍后讨论多态性的主题时,依赖关系 章节。 see reference

因此,将Load() 放入父级是不好的设计。

其次:你说:

加载保存的元素时,您不知道要加载的类。

所以,您的客户只依赖于Save() 方法。因此,它们不是您的客户和父母之间的依赖关系。你的客户只依赖myIntrface

最后:您的客户应该从myInterface 定义一个属性。然后,您只需要另一个将对象注入到您的客户端属性的类。 (如 Factory 类 - 作为 @VishalRaja 的答案 - 或 Dependency Injector 类)。然后您可以将所有需要的配置放入其中,以决定应该传递哪些类实例。

【讨论】:

  • 感谢您的详细回答。我试图修改我的设计以使用您和@Vishal_Raja 提到的工厂。你会更同意这个新设计吗?当您说:“您的客户应该从 'myInterface' 定义一个属性”时,我不确定我是否理解您,您能否提供更多详细信息?
  • 抱歉,我用的是 Java。在 Java 中,我们可以从接口定义一个属性,例如:private myInterface x;。然后我们可以将任何实现myInterface的类的实例设置为x
  • @user3091275,不需要在子类或myInterface中添加load()方法。把它放在工厂类里。最好重命名为getInstance()
【解决方案2】:

为什么不创建一个单独的工厂类来确保根据子类类型正确保存实现?

【讨论】:

  • 问题不在调用 save 方法时,而是在从基类调用 load 方法时。也许您的意思是加载而不是保存?
  • 是的,我只是想向您暗示一种更简洁的设计,您可以在专用工厂中实例化不同的子类。
  • 谢谢,我用工厂的新设计更新了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-30
  • 2010-12-05
相关资源
最近更新 更多