I try to implement multiple concrete classes, which share the same API. The base functionalities between these classes are the same, but they support different types of configuration (among shared ones). I would like to keep the implementation between these concrete classes as separate as possible.
Therefore I came up with an (abstract) base class which defines the API, but I am not sure how to define the function arguments.
-
Common config containing all possibilities
-
(+) Same API for all implementations.
-
(-) API suggests certain unsupported configurations. (It might be in the future though).
Perhaps I would need to address this in the doc and/or even raise an exception in case of inproper use.
-
(-) In case of a new config attribute gets added, the other already existing concrete classes don’t address this new attribute.
@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`.
-
-
Generic signature of base class
class AbstractA: def func_z(self, *args, **kwargs): # Or expect `CommonCfg` which only contains common config parameters (e.g. `cfg_1`)
For
func_z
,ClassB
&ClassC
would expect their specificCfgB
andCfgC
, respectively.
In a perfect scenario I could just exchange objects of different concrete implementations (at least as long as only their common configs are relevant).
E.g.
...
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)
Note: Link to question in stackoverflow, but actually it fits better here.
Guti_Haz is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
1