Python:没有抽象方法的抽象类层次结构

时间:2019-12-13 04:47:53

标签: python inheritance abstract-class

所以,这是一个问题:

  1. 我想定义一个抽象类,例如AbstractA,它不需要子类来实现其任何方法,而是扩展其功能。用Java来说就是接口类。

  2. 此外,我希望能够创建AbstractB中具有相同属性的抽象子类,例如AbstractA,但是有些方法会重新定义或扩展基类方法。 / p>

我不想让类(AbstractA)抽象,例如through the check of class name in __init__ or __new__,因为这将需要抽象子类(AbstractB)来重新定义该方法及其主要功能,即构造或初始化新实例。或致电我更希望避免使用的super().__init__(...)(也许我在这里错了)。

所以,我想要这样的东西:

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

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

class AbstractB(AbstractA):
    # do not duplicate initialization stuff here, inherit instead

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

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

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

# Instantiating AbstractA or AbstractB should result in error.
# Instantiating AX or BX should not.

下面我有一个可能的解决方案。 有没有我忽视的缺点?更好的解决方案?

谢谢!

3 个答案:

答案 0 :(得分:0)

可能的解决方法:

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>

答案 1 :(得分:0)

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>
>>> 

答案 2 :(得分:0)

在Python中,您可能将“抽象”基类实现为混入。您不需要做任何特别的事情。按照惯例,您可以在名称中添加Mixin来表示它不是要直接实例化的,而只是用作其他类的基类。

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):
    ...