I have different implementations of a feature that only differ in some methods, so I want to use a Parent
class to prevent duplicated code.
The methods that differ I want to implement with an abstract method to ensure the structure is the same in all children.
The problem is that each child uses its own enums that need to be passed as arguments to the abstract methods.
The enums have defined necessary values and can't be combined as the values could overlap.
Child1
will only use the Child1 enums, Child2
only Child2 enums (more children are also possible).
In addition I'm limited to Python 3.9.
I thought of using typing.Union
to allow continuous typing and typing.cast
to get the correct type within the methods.
import typing
from abc import ABC, abstractmethod
from enum import IntEnum, IntFlag
class Child1Enum(IntEnum):
A = 1
B = 2
class Child1Result(IntFlag):
W = 1
X = 4
class Child2Enum(IntEnum):
C = 1
D = 2
class Child2Result(IntFlag):
Y = 1
Z = 2
class Parent(ABC):
@abstractmethod
def abstract_method(
self, argument: typing.Union[Child1Enum, Child2Enum]
) -> typing.Union[Child1Result, Child2Result]:
pass
class Child1(Parent):
def abstract_method(
self, argument: typing.Union[Child1Enum, Child2Enum]
) -> typing.Union[Child1Result, Child2Result]:
argument = typing.cast(Child1Enum, argument)
# work ...
return Child1Result.X
class Child2(Parent):
def abstract_method(
self, argument: typing.Union[Child1Enum, Child2Enum]
) -> typing.Union[Child1Result, Child2Result]:
argument = typing.cast(Child2Enum, argument)
# work ...
return Child2Result.Y
Is this the right way to do it or is there a better way, because I think this works against the idea of abstract methods?
You could make Parent
generic:
import typing
from abc import ABC, abstractmethod
from enum import IntEnum, IntFlag
class Child1Enum(IntEnum):
A = 1
B = 2
class Child1Result(IntFlag):
W = 1
X = 4
class Child2Enum(IntEnum):
C = 1
D = 2
class Child2Result(IntFlag):
Y = 1
Z = 2
TEnum = typing.TypeVar('TEnum', Child1Enum, Child2Enum)
TResult = typing.TypeVar('TResult', Child1Result, Child2Result)
class Parent(typing.Generic[TEnum, TResult], ABC):
@abstractmethod
def abstract_method(
self, argument: TEnum
) -> TResult:
pass
class Child1(Parent[Child1Enum, Child1Result]):
def abstract_method(
self, argument: Child1Enum
) -> Child1Result:
return Child1Result.X
class Child2(Parent[Child2Enum, Child2Result]):
def abstract_method(
self, argument: Child2Enum
) -> Child2Result:
return Child2Result.Y
Mypy said: Success: no issues found in 1 source file
, so I think it should work for you.