我尝试实现多个共享相同 API 的具体类。这些类之间的基本功能是相同的,但它们支持不同类型的配置(在共享配置之间)。我希望这些具体类之间的实现尽可能分开。
因此我想出了一个(抽象)基类来定义 API,但我不确定如何定义函数参数。
包含所有可能性的通用配置
(+) 所有实现都使用相同的 API。
(-) API 建议某些不受支持的配置。 (不过可能是在未来)。
也许我需要在文档中解决这个问题,并且/或者甚至在使用不当的情况下引发异常。
(-) 如果添加新的配置属性,其他现有的具体类不会处理这个新属性。
@dataclass
class CommonCfg:
cfg_1: Optional[int] = None
cfg_2: Optional[int] = None
cfg_3: Optional[int] = None
class AbstractA:
@abstractmethod
def func_z(self, cfg: CommonCfg):
class B(AbstractA):
def func_z(self, cfg: CommonCfg):
# Does not use `cfg_3`.
class C(AbstractA):
def func_z(self, cfg: CommonCfg):
# Does not use `cfg_2`.
基类的通用签名
class AbstractA:
def func_z(self, *args, **kwargs):
# Or expect `CommonCfg` which only contains common config parameters (e.g. `cfg_1`)
对于
func_z
、ClassB
和 ClassC
分别期望其具体的 CfgB
和 CfgC
。
在完美的场景中,我可以交换不同具体实现的对象(至少只要它们的通用配置相关)。 例如
...
b = ClassB()
c = ClassC()
cfg = CommonCfg()
b.func_z(cfg)
# I would like to have the least amount of hassle replacing it, e.g. with:
# c.func_z(cfg)
一种可能的解决方案是将基本功能委托给基类。这样,如果您向
CommonCfg
对象添加其他参数,则不必更新基类方法。代码可能看起来像这样:
class AbstractA:
def func_z(self, cfg: CommonCfg):
# Do some work using cfg
class B(AbstractA):
def func_z(self, cfg: CommonCfg):
super().func_z(cfg)
# Do some additional work
class C(AbstractA):
def func_z(self, cfg: CommonCfg):
super().func_z(cfg)
# Do some additional work
这还可以让您检查
cfg
对象是否受支持
在调用基本方法之前调用方法。
对于不支持的配置,您已经提到了一个应该为您提供最大灵活性的解决方案。只需为每种方法添加详细说明不支持哪些配置的文档就应该给出任何
体面的用户有足够的信息来正确使用 API。引发异常还可以帮助用户检测代码中的任何错误。