Gonen I
Gonen I

Reputation: 6117

Can I mark a class abstract even if all its methods are implemented?

Is there a way to mark a python class as abstract or un-instantiable even if all its abstract methods have been implemented?

class Component(ABC):
    @abstractmethod
    def operation(self) -> None:
        pass

class Decorator(Component): # I would like this class to be abstract
    def operation(self) -> None:
        print("basic operation")

The only workaround I found is to choose some method in the class to have both implementation and @abstractmethod decorator, but then python requires derivers of the child abstract class to re-implement the method.

This too can be worked around by having the child class calling super() , but pylint complains that this is a useless call.

class Component(ABC):
    @abstractmethod
    def operation(self) -> None:
        pass

class Decorator(Component): # I would like this class to be abstract
    @abstractmethod
    def operation(self) -> None:
        print("basic operation")

class ConcreteDecorator(Decorator): 
    def operation(self) -> None: # python makes child class re-implement
        super().operation()  # pylint complains about useless super delegation

Is there a better way to do this?
I tried using a method with implementation and @abstractmethod decorator, but then deriving classes need to reimplement. I'm looking for a solution at "compile time", not a run time error.

Upvotes: 6

Views: 510

Answers (1)

aaron
aaron

Reputation: 43103

Create a helper class that overrides the __new__ function to check whether cls.__bases__ contains itself.

class UnInstantiable:
    def __new__(cls, *args, **kwargs):
        if __class__ in cls.__bases__:
            raise TypeError(f"Can't instantiate un-instantiable class {cls.__name__}")

        return super().__new__(cls)

Usage:

# class Decorator(Component):                # Add UnInstantiable base class
class Decorator(Component, UnInstantiable):  # like this
    def operation(self) -> None:
        print("basic operation")


Decorator()  # TypeError: Can't instantiate un-instantiable class Decorator

Upvotes: 1

Related Questions