从 ABC 和 QMainWindow 继承的抽象类

问题描述

from abc import ABC,abstractmethod
from PyQt5.QtWidgets import QMainWindow


class _ControlGUI(QMainWindow,ABC):
    pass

上面非常简单的代码引发了一个我不太清楚的错误

类型错误元类冲突:派生类的元类必须 是其所有基类元类的(非严格)子类

我的目标是定义一个具有强制结构/属性的基类 _ControlGUI;然后定义从它继承的多个具体类,以及附加的功能/属性。所有这些具体类都是小图形用户界面,因此继承自 QMainWindow,因此我认为最好让抽象类直接继承自 QMainWindow。然而,这似乎是不可能的。

这个问题的最佳设计、解决方案是什么?我目前的想法是定义没有 QMainWindow 的抽象类,并让所有具体类继承自 _ControlGUIQMainWindow

解决方法

正如错误所说,您必须创建一个元类,它是所涉及类的每个元类的子类。

PyQT Widgets 的元类可能不是为了与其他元类协同工作而设计的——这将取决于运气。 ABC 的元类,abc.ABCMeta(出于说明目的,我在下面将其称为 type(ABC))如果更适合协作继承,那么在派生元类时将其放在首位将使您有更好的机会获得实际工作的东西。 (即,除其他外,它将在其方法中使用 super() 调用,而不是硬编码对 type.<method> 的调用)。

获得派生元类后,只需在继承基类上使用它。由于所有示例都是一行代码,查看结果很有趣,我只是在交互环境中写了一些东西:

In [1]: from PyQt5.QtWidgets import QMainWindow

In [2]: from abc import ABC,ABCMeta

In [3]: class A(QMainWindow,ABC): pass
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-86552c93e708> in <module>
----> 1 class A(QMainWindow,ABC): pass

TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

In [4]: class Meta(type(ABC),type(QMainWindow)): pass

In [5]: class B(QMainWindow,ABC,metaclass=Meta): pass

顺便提一下,无论 Qt 文档(以及其他图形工具包)怎么说,使用小部件的子类来创建您的应用程序可能是一个主要的痛苦。如果您只是实例化小部件并将它们作为属性引用到一个只继承与您的项目相关的事物的普通类中,那么与从 QMainWindow 继承开始相比,您可能会走得更远。>