Skip to content Skip to sidebar Skip to footer

Python: Hierarchy Of Abstract Classes Without Abstract Methods

So, here is a problem: I want to define an abstract class, let's say AbstractA, which does not require subclasses to implement any of its methods, but rather to extend its functio

Solution 1:

Here's possible solution:

class AbstractA:
    _is_abstract = True

    def __init__(self):
        if self._is_abstract:
            raise RuntimeError("Abstract class instantiation.")
        # do initialization stuff

    def __init_subclass__(self):   # is called every time class is subclassed
        self._is_abstract = False  # thus makes sure abstract check fails on a subclass

class AbstractMixin:
    def __init_subclass__(self):
        self._is_abstract = True

class AbstractB(AbstractMixin, AbstractA):  # AbstractMixin takes precendence on MRO,
    # inherit __init__                      # so the class abstract check returns True.

    def __init_subclass__(self):
        self._is_abstract = False

class A(AbstractA):
    pass

class B(AbstractB):
    pass

AbstractA()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in __init__
RuntimeError: Abstract class instantiation.

AbstractB()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in __init__
RuntimeError: Abstract class instantiation.

A()
<__main__.A object at 0x7f0bba5112e8>

B()
<__main__.B object at 0x7f0bba511438>

Solution 2:

class A(object):

    def __init__(self):
        if self.__class__ == A:
            raise RuntimeError("Abstract class instantiation.")
        print(self.__class__.__name__)


class B(A):
    pass


>>> A()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in __init__
RuntimeError: Abstract class instantiation.
>>> B()
B
<__main__.B object at 0x7f8c816a58d0>
>>> 


Solution 3:

In Python, you would probably implement the "abstract" base classes as mix-ins. There's nothing special you need to do; by convention, you would add Mixin to the name to indicate that it isn't meant to be instantiated directly, but simply used as a base class for other classes.

class AMixin:
    def __init__(self):
        # do initialization stuff

    def very_common_method(self, ...):
        # do very common stuff

class BMixin(AMixin):
    # do not duplicate initialization stuff here, inherit instead

    def less_common_method(self, ...):
        # do less common stuff

class AX(AMixin):
    def specific_method_1(self, ...):

class BX(BMixin):
    def specific_method_2(self, ...):

class Foo:
    ...

class Bar(Foo, BMixin):
    ...

Post a Comment for "Python: Hierarchy Of Abstract Classes Without Abstract Methods"