所以,这是一个问题:
我想定义一个抽象类,例如AbstractA
,它不需要子类来实现其任何方法,而是扩展其功能。用Java来说就是接口类。
此外,我希望能够创建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.
下面我有一个可能的解决方案。 有没有我忽视的缺点?更好的解决方案?
谢谢!
答案 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):
...