I'm trying to create an abstract enum (Flag
actually) with an abstract method.
My final goal is to be able to create a string representation of compound enums, based on the basic enums I defined.
I'm able to get this functionality without making the class abstract.
This is the basic Flag
class and an example implementation:
from enum import auto, Flag
class TranslateableFlag(Flag):
@classmethod
def base(cls):
pass
def translate(self):
base = self.base()
if self in base:
return base[self]
else:
ret = []
for basic in base:
if basic in self:
ret.append(base[basic])
return " | ".join(ret)
class Students(TranslateableFlag):
ALICE = auto()
BOB = auto()
CHARLIE = auto()
ALL = ALICE | BOB | CHARLIE
@classmethod
def base(cls):
return {Students.ALICE: "Alice", Students.BOB: "Bob",
Students.CHARLIE: "Charlie"}
An example usage is:
((Students.ALICE | Students.BOB).translate())
[Out]: 'Alice | Bob'
Switching to TranslateableFlag(Flag, ABC)
fails due to MetaClass conflicts.
(I didn't understand this post - Abstract Enum Class using ABCMeta and EnumMeta, so I'm not sure if it's answering my question).
I would like get a functionality like this somehow:
@abstractclassmethod
@classmethod
def base(cls):
pass
Is it possible to achieve this?
Yes, you can define abstract methods in an enum declaration if and only if all enum values have custom class bodies with implementations of those methods (i.e. no concrete enum value may be lacking an implementation).
Java Language Enums Enums with Abstract MethodsEnums can define abstract methods, which each enum member is required to implement. This allows for each enum member to define its own behaviour for a given operation, without having to switch on types in a method in the top-level definition.
enum inheritance lang. Enum is an abstract class. This is the common base class of all Java enumeration types.
10) You can not create an instance of enums by using a new operator in Java because the constructor of Enum in Java can only be private and Enums constants can only be created inside Enums itself. 11) An instance of Enum in Java is created when any Enum constants are first called or referenced in code.
Here's how to adapt the accepted answer to the question Abstract Enum Class using ABCMeta and EnumMeta to create the kind of abstract Enum
class you want:
from abc import abstractmethod, ABC, ABCMeta
from enum import auto, Flag, EnumMeta
class ABCEnumMeta(ABCMeta, EnumMeta):
def __new__(mcls, *args, **kw):
abstract_enum_cls = super().__new__(mcls, *args, **kw)
# Only check abstractions if members were defined.
if abstract_enum_cls._member_map_:
try: # Handle existence of undefined abstract methods.
absmethods = list(abstract_enum_cls.__abstractmethods__)
if absmethods:
missing = ', '.join(f'{method!r}' for method in absmethods)
plural = 's' if len(absmethods) > 1 else ''
raise TypeError(
f"cannot instantiate abstract class {abstract_enum_cls.__name__!r}"
f" with abstract method{plural} {missing}")
except AttributeError:
pass
return abstract_enum_cls
class TranslateableFlag(Flag, metaclass=ABCEnumMeta):
@classmethod
@abstractmethod
def base(cls):
pass
def translate(self):
base = self.base()
if self in base:
return base[self]
else:
ret = []
for basic in base:
if basic in self:
ret.append(base[basic])
return " | ".join(ret)
class Students1(TranslateableFlag):
ALICE = auto()
BOB = auto()
CHARLIE = auto()
ALL = ALICE | BOB | CHARLIE
@classmethod
def base(cls):
return {Students1.ALICE: "Alice", Students1.BOB: "Bob",
Students1.CHARLIE: "Charlie"}
# Abstract method not defined - should raise TypeError.
class Students2(TranslateableFlag):
ALICE = auto()
BOB = auto()
CHARLIE = auto()
ALL = ALICE | BOB | CHARLIE
# @classmethod
# def base(cls):
# ...
Result:
Traceback (most recent call last):
...
TypeError: cannot instantiate abstract class 'Students2' with abstract method 'base'
Here is a fix of the accepted answer for python 3.8. The only change is to the ABCEnumMeta
. The rest is copy-pasted from the original answer to provide a runnable example. Also tested on python 3.6.2.
from abc import abstractmethod, ABC, ABCMeta
from enum import auto, Flag, EnumMeta
class ABCEnumMeta(EnumMeta, ABCMeta):
pass
class TranslateableFlag(Flag, metaclass=ABCEnumMeta):
@classmethod
@abstractmethod
def base(cls):
pass
def translate(self):
base = self.base()
if self in base:
return base[self]
else:
ret = []
for basic in base:
if basic in self:
ret.append(base[basic])
return " | ".join(ret)
class Students1(TranslateableFlag):
ALICE = auto()
BOB = auto()
CHARLIE = auto()
ALL = ALICE | BOB | CHARLIE
@classmethod
def base(cls):
return {Students1.ALICE: "Alice", Students1.BOB: "Bob",
Students1.CHARLIE: "Charlie"}
class Students2(TranslateableFlag):
ALICE = auto()
BOB = auto()
CHARLIE = auto()
ALL = ALICE | BOB | CHARLIE
# Abstract method not defined - should raise TypeError.
# @classmethod
# def base(cls):
# ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With