Oop 从基类加载子类

Oop 从基类加载子类,oop,inheritance,design-patterns,Oop,Inheritance,Design Patterns,我有一个基类BaseClass,它有多个子类子类1,子类2。实际上,该程序仅适用于其中一个子类的实例。子类实现了一个带有save方法的接口。加载保存的元素时,您不知道要加载的类。因此,我考虑在基类中使用load方法,但这提出了一个问题:如何从基类中的一个子类实例化元素 为了清晰起见,这里有一些简单的代码: 类基类: def加载(自): #子类的荷载元素 返回子类_元素 类myInterface: __元类_uu=ABCMeta @抽象方法 def保存(自我): 引发未实现的错误 类子类1(基类,

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

为了清晰起见,这里有一些简单的代码:
类基类:
def加载(自):
#子类的荷载元素
返回子类_元素
类myInterface:
__元类_uu=ABCMeta
@抽象方法
def保存(自我):
引发未实现的错误
类子类1(基类,myInterface):
def保存(自我):
#保存元素
类子类2(基类,myInterface):
def保存(自我):
#保存元素
我也愿意接受任何支持不同设计的建议。我不确定我没有实现反模式

编辑1:添加工厂类

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

类子类加载器:#这是我们的工厂类
注册的_子类={}#子类的静态dict
@静力学方法
def寄存器(类名称,类):
SubClassLoader.registered_子类[classname]=类
@静力学方法
def get_实例(文件路径):
classname,arguments=get\u classname(文件路径)
如果SubClassLoader.registered_子类中的classname:
返回SubClassLoader.registered_子类[classname](参数)
其他:
引发类型错误(“未知类%s”%classname)
类基类:
通过
类myInterface:
__元类_uu=ABCMeta
@抽象方法
def保存(自我):
引发未实现的错误
类子类1(基类,myInterface):
def保存(自我):
#保存元素
类子类2(基类,myInterface):
def保存(自我):
#保存元素

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

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

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

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

为什么?

如果基类知道它们的派生类,那么它就是 这意味着,如果将新的派生类添加到基类,则代码 基类的属性将需要修改。这是一种不可取的做法 基础中捕获的抽象与派生的抽象之间的依赖关系 上课。我们将看到更好的解决方案来解决这些类型的问题 当我们在本文后面讨论多态性主题时 章

因此,将
Load()
放入父级是一种糟糕的设计

其次:你说:

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

因此,您的客户端只依赖于
Save()
方法。因此,它们不是客户和家长之间的依赖关系。您的客户端仅依赖于
myIntrface


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

这是关于一般的OOP,还是专门关于Python?Pythonb上下文中的一般OOP,但主要是一般OOP问题不是在调用save方法时,而是在从基类调用load方法时。也许你的意思是加载而不是保存?是的,我只是想告诉你一个更干净的设计,你可以在一个专用工厂中实例化不同的子类。谢谢,我用一个新的设计更新了我的问题,使用了工厂。谢谢你的详细回答。我试图修改我的设计,使用你和@Vishal_Raja提到的工厂。你更同意这种新设计吗?当你说:“你的客户机应该从‘myInterface’中定义一个属性”时,我不确定我是否理解你的意思,你能提供更多的细节吗?对不起,我用的是Java。在Java中,我们可以从如下接口定义属性:
private myInterface x。然后我们可以将实现
myInterface
的任何类的实例设置为
x
@user3091275,无需在子类或
myInterface
中添加
load()
方法。把它放在工厂里。最好将其重命名为
getInstance()