Reputation: 1330
Suppose I have a parent class Parent
, with abstract method load
that is implemented in its childs classes. Now, I have two child classes childA
and childB
, both inheriting from Parent
. The implementation of load
for childA
and childB
identical. But this implementation of load
calls another method, get_paths
, that is specific to childA
and childB
. Parent is something like:
from abc import ABC, abstractmethod
class Parent(ABC):
def __init__(self, *params):
# set up the params
@abstractmethod
def load(self, *params):
# loads files, according to each children
def process(self, *params):
# process the loaded files
And then the children:
class childA(Parent):
def __init__(self, *paramsP, *paramsA):
super().__init__(*paramsP)
# Set up the specific paramsA
def get_paths(self, *params):
# specific implementation to childA
def load(self, *params):
# Calls the self.get_paths method, identical to childB.load
class childB(Parent):
def __init__(self, *paramsP, *paramsB):
super().__init__(*paramsP)
# Set up the specific paramsB
def get_paths(self, *params):
# specific implementation to childB
def load(self, *params):
# Calls the self.get_paths method, identical to childA.load
How can I reuse the code from load
in both childA
and childB
, but have the get_paths
implementation be specific to each class? I tried two approaches:
(1) Have childB
inherit from childA
instead, and override the implementation of get_paths
. In this approach, I have:
class childB(childA):
def __init__(self, *paramsP, *paramsB):
super().__init__(*paramsP)
# Set up the specific paramsB
def get_paths(self, *params):
# specific implementation to childB
I called it as:
b = childB(...)
b.load(...)
However, when I call `childB.load`, the `get_paths` called inside of it is `childA.get_paths`. I noticed that because I was getting an error when running `b.load`, so tried putting a break point with `ipdb` inside of `childB.get_paths`, but execution did not stop. But when I put the breaking point inside of `childA.get_paths`, it did break.
(2) Implement another class, `AB`, with the following definition:
```python
class AB(Parent):
def __init__(self, *paramsP):
super().__init__(*paramsP)
@abstract method
def get_paths(self, *params):
# To be implemented in childA and childB
def load(self, *params):
# Implements the load from childA and childB
and then have childA
and childB
both inherit from AB
instead, and implement their specific get_paths
. However, this did not work as well, as I get the error: TypeError: Can't instantiate abstract class ChildB with abstract methods _AB__get_paths
.
It is important to add I cannot implement load
in Parent
because there are other classes ( childC
, childD
, ...) with unique load
implementations.. I just want to reuse this code between childA
and childB
So, what is the correct way to solve this?
Upvotes: 1
Views: 602
Reputation: 8572
Unless you want Parent
to be inherited with abstract .load
, just put implementation into Parent
.
If .load
is common only for this two childs – you can inherit from Parent
with 3rd child like LoadMixin
and inherit both Parent
and mixin
One approach would be:
class LoadableChild(Parent):
def load(self, *params): ...
class childA(LoadableChild):
def get_paths(self, *params): ...
class childB(LoadableChild):
def get_paths(self, *params): ...
Another is:
class LoadBase:
def load(self, *params): ...
class childA(LoadBase, Parent):
def get_paths(self, *params): ...
class childB(LoadBase, Parent):
def get_paths(self, *params): ...
Note the order of inheritance in later approach, if you inherit parent as first superclass, there is no easy way around:
Parent
– there's no unambiguous MROobject
– there's instantiation error on abstract .load
.It's matter of preference, I'd say, for me personally first approach is cleaner
Upvotes: 1