如何继承 ABC 和另一个 class
How to inherit from ABC and another class
我有一个class
class A(ABC):
@abstractmethod
def m():
pass
和一堆继承自它的 classes。
class M1(A):
...
class M2(A):
...
...
其中一些有很多共同点,因为它们共享很多功能,因此我想介绍一个公共基础 class,它本身继承自 A
,但它不介绍任何新的 @abstractmethod
方法:
A
|
+----+----+
| | |
M1 M2 B
|
+--+--+
| |
K1 K2
class B
的定义应该是什么样的?
我在 Python 3.8
编辑: 我特意询问 PyCharm 告诉我“B 必须继承所有抽象方法”
您可以简单地使用
class B(A):
pass
或所有儿童通用的任何其他代码,但没有 m
。由于缺少 m
.
,这仍然是抽象的
另一种方法是使用
class B(A, ABC):
pass
在我看来这不太好。这说明 B
既是 A
又是 ABC
,而前一个替代说明 B
是 A
,它是 [=16] =] 只要 A
本身就是 ABC
。
考虑一下您稍后决定 A
毕竟不是 ABC
的情况。对于 M1
和 M2
,无需进行任何更改。对于 B
,您现在还需要将其删除为 ABC
。虽然确保 A
和 B
在子类化 ABC
中同步在代码维护方面并不是一个巨大的开销,但我认为这确实表明设计有问题,PyCharm 尽管有关于前一个替代方案的警告(我会将其抑制为误报)。
在您的特定情况下,您不需要混合任何东西。我个人不使用 Pycharm,但是创建 B
作为 A
的子类工作得很好并且 python 不会抱怨。
>>> from abc import ABC, abstractmethod
>>> class A(ABC):
... @abstractmethod
... def m(self):
... pass
...
>>> class B(A):
... def common_method(self) -> str:
... return 'b'
...
>>> class K1(B):
... def m(self) -> str:
... return 'k1'
...
>>> class K2(B):
... def m(self) -> str:
... return 'k2'
...
>>> k1 = K1()
>>> k2 = K2()
>>> k1.m()
'k1'
>>> k2.m()
'k2'
>>> k1.common_method()
'b'
>>> k2.common_method()
'b'
>>> # However you can't do this
>>> b = B()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class B with abstract methods m
如果你有不同但相似的结构(不是直接问题但仍然相关)
A <----- this is not abstract
|
+----+----+
| | |
M1 M2 B <------ you want this to be abstract and also group some
| functionality for K1 and K2
+--+--+
| |
K1 K2
您可以通过定义 metaclass
而不是将 ABC
和 A
子类化为混合(元类无论如何都会完成所有工作),而无需混合 类 .以下是您的操作方法。
>>> from abc import ABCMeta, abstractmethod
>>> class A:
... def m(self) -> str:
... return 'a'
...
>>> class B(A, metaclass=ABCMeta):
... @abstractmethod
... def n(self):
... pass
... def common_method(self) -> str:
... return 'b'
...
>>> class K1(B):
... def n(self) -> str:
... return 'k1'
...
>>> class K2(B):
... def n(self) -> str:
... return 'k2'
...
>>> k1 = K1()
>>> k2 = K2()
>>> k1.m()
'a'
>>> k2.m()
'a'
>>> k1.n()
'k1'
>>> k2.n()
'k2'
>>> k1.common_method()
'b'
>>> k2.common_method()
'b'
>>>
我有一个class
class A(ABC):
@abstractmethod
def m():
pass
和一堆继承自它的 classes。
class M1(A):
...
class M2(A):
...
...
其中一些有很多共同点,因为它们共享很多功能,因此我想介绍一个公共基础 class,它本身继承自 A
,但它不介绍任何新的 @abstractmethod
方法:
A
|
+----+----+
| | |
M1 M2 B
|
+--+--+
| |
K1 K2
class B
的定义应该是什么样的?
我在 Python 3.8
编辑: 我特意询问 PyCharm 告诉我“B 必须继承所有抽象方法”
您可以简单地使用
class B(A):
pass
或所有儿童通用的任何其他代码,但没有 m
。由于缺少 m
.
另一种方法是使用
class B(A, ABC):
pass
在我看来这不太好。这说明 B
既是 A
又是 ABC
,而前一个替代说明 B
是 A
,它是 [=16] =] 只要 A
本身就是 ABC
。
考虑一下您稍后决定 A
毕竟不是 ABC
的情况。对于 M1
和 M2
,无需进行任何更改。对于 B
,您现在还需要将其删除为 ABC
。虽然确保 A
和 B
在子类化 ABC
中同步在代码维护方面并不是一个巨大的开销,但我认为这确实表明设计有问题,PyCharm 尽管有关于前一个替代方案的警告(我会将其抑制为误报)。
在您的特定情况下,您不需要混合任何东西。我个人不使用 Pycharm,但是创建 B
作为 A
的子类工作得很好并且 python 不会抱怨。
>>> from abc import ABC, abstractmethod
>>> class A(ABC):
... @abstractmethod
... def m(self):
... pass
...
>>> class B(A):
... def common_method(self) -> str:
... return 'b'
...
>>> class K1(B):
... def m(self) -> str:
... return 'k1'
...
>>> class K2(B):
... def m(self) -> str:
... return 'k2'
...
>>> k1 = K1()
>>> k2 = K2()
>>> k1.m()
'k1'
>>> k2.m()
'k2'
>>> k1.common_method()
'b'
>>> k2.common_method()
'b'
>>> # However you can't do this
>>> b = B()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class B with abstract methods m
如果你有不同但相似的结构(不是直接问题但仍然相关)
A <----- this is not abstract
|
+----+----+
| | |
M1 M2 B <------ you want this to be abstract and also group some
| functionality for K1 and K2
+--+--+
| |
K1 K2
您可以通过定义 metaclass
而不是将 ABC
和 A
子类化为混合(元类无论如何都会完成所有工作),而无需混合 类 .以下是您的操作方法。
>>> from abc import ABCMeta, abstractmethod
>>> class A:
... def m(self) -> str:
... return 'a'
...
>>> class B(A, metaclass=ABCMeta):
... @abstractmethod
... def n(self):
... pass
... def common_method(self) -> str:
... return 'b'
...
>>> class K1(B):
... def n(self) -> str:
... return 'k1'
...
>>> class K2(B):
... def n(self) -> str:
... return 'k2'
...
>>> k1 = K1()
>>> k2 = K2()
>>> k1.m()
'a'
>>> k2.m()
'a'
>>> k1.n()
'k1'
>>> k2.n()
'k2'
>>> k1.common_method()
'b'
>>> k2.common_method()
'b'
>>>