当前位置: 首页 > 面试题库 >

三重继承会导致元类冲突...有时

傅雪松
2023-03-14
问题内容

看起来我偶然发现了一个元类地狱,即使我不想做任何事情。

我正在使用PySide在Qt4中编写一个应用程序。我想将事件驱动的部分与UI定义分开,UI定义是从Qt Designer文件生成的。因此,我创建了一个“
controller”类,但是为了简化我的生活,我还是对它们进行了多重继承。一个例子:

class BaseController(QObject):
    def setupEvents(self, parent):
        self.window = parent

class MainController(BaseController):
    pass

class MainWindow(QMainWindow, Ui_MainWindow, MainController):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.setupUi(self)
        self.setupEvents(self)

这按预期工作。它也有继承自(QDialogUi_DialogBaseController)。但是,当我子类化BaseController并尝试从所述子类继承(代替BaseController)时,会收到错误消息:

TypeError:调用元类基础元类冲突时出错:派生类的元类必须是其所有基础元类的(非严格)子类

澄清:这两个QMainWindowQDialog继承QObjectBaseController由于Qt事件系统的特殊性,还必须从中继承。Ui_类仅继承自简单的Python对象类。我搜索了解决方案,但所有解决方案都涉及故意使用元类的情况。因此,我必须做一些非常错误的事情。

编辑:通过添加图形,我的描述可能会更清晰。

工作示例:

QObject
|      \___________________
|            object        |
QMainWindow     |          BaseController
|      /---Ui_MainWindow   |
|      |                   MainController
MainWindow-----------------/

另一个工作示例:

QObject
|      \___________________
|            object        |
QDialog         |          BaseController
|      /---Ui_OtherWindow  |
|      |                   |
OtherWindow----------------/

不起作用的示例:

QObject
|      \___________________
|            object        |
QDialog         |          BaseController
|      /---Ui_OtherWindow  |
|      |                   OtherController
OtherWindow----------------/

问题答案:

错误消息表明您在层次结构中的某个位置有两个冲突的元类。您需要检查每个类和QT类,以找出冲突的位置。

这是设置相同情况的一些简单示例代码:

class MetaA(type):
    pass
class MetaB(type):
    pass
class A:
    __metaclass__ = MetaA
class B:
    __metaclass__ = MetaB

我们不能直接对这两个类进行子类化,因为python不知道要使用哪个元类:

>>> class Broken(A, B): pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
  metaclass conflict: the metaclass of a derived class must be a (non-strict)
  subclass of the metaclasses of all its bases

错误试图告诉我们的是,我们需要通过引入第三个元类来解决这两个元类之间的冲突,这是基类中所有元类的子类。

我不确定是否比错误消息本身更清晰,但是基本上,您可以通过执行以下操作来修复它:

class MetaAB(MetaA, MetaB):
    pass

class Fixed(A, B):
    __metaclass__ = MetaAB

现在,此代码可以编译并正确运行。当然,在实际情况下,您的解决冲突的元类将不得不决定采用哪种父元类行为,您必须根据应用程序的需求自行确定哪些行为。

记住,你的继承类只得到 一个
两元类的。__init__方法有时会完成所有工作,因此在许多情况下,您将不得不添加一个__init__以某种方式调用两者的方法,以帮助他们相处。



 类似资料:
  • 问题内容: 我需要一个类的双重继承。我尝试了几种语法,但我不了解元类的概念。 问题答案: 您遇到的问题是,您尝试从其继承的类具有不同的元类: 因此,python无法确定哪个应该是新创建的类的元类。在这种情况下,它必须是一个继承自(或对于较旧的PyQt5版本)和的类。 因此,可以通过显式引入诸如metaclass之类的类来解决元类冲突: 如果需要更详细的描述,那么本文是一个好的开始。 但是,我并不真

  • 我正在开发jira插件。当我尝试部署它时,我收到一个错误: 创建URL中定义了名为“userService”的bean时出错[bundle://205.0:1/com/softwareplant/tool/service/UserService.class]:通过构造函数实例化Bean失败;嵌套的例外是java。lang.LinkageError:加载程序约束冲突:解析方法“org.slf4j.i

  • 我使用的是MGSplitViewClass(链接),我很难正确设置UICollectionView的大小。在上述拆分视图中,我在主视图中有一组四个UIView,其中包含更健壮的视图(表视图、标签组和集合视图)。 首先,我尝试在nib中添加UICollectionView,并通过编程创建了一个集合视图控制器,并将其连接到nib的集合视图。我一试collectionViewController,这就失

  • fun setCollection(collection:(Mutable)Collection !):KotlinClass中定义的单元 无论我做什么,都没有办法只用Kotlin代码来编译它。 再现情况的代码: Java本身就不存在这个问题。所以我猜测这可能与平台类型有关(不是)。 有没有一个优雅的解决方案来解决这个问题,最好不需要编写Java代码?还是应该在Kotlin编译器中解决这个问题?

  • 问题内容: 运行以下 xjc 命令会引发错误: 尽管我了解JAXB绑定以及XJC中的冲突是什么,但我不了解当前模式中的冲突在哪里。 我该如何解决? 谢谢, 皮埃尔 更新:这是错误的上下文: 问题答案: 我将引用网上JAXB上最官方的非官方指南。 当架构包含外观相似的元素/类型名称时,它们可能导致“两个声明在ObjectFactory类中引起冲突”错误。更准确地说,对于所有类型和许多元素中的每一个(

  • 问题内容: 我已经在BabelJS和MDN(根本没有任何信息)上完成了大部分研究工作,但是请随时告诉我是否在寻找有关ES6Spec的更多信息时不够谨慎。 我想知道ES6是否以与其他鸭子类型语言相同的方式支持多重继承。例如,我可以做类似的事情: 将多个类别扩展到新类别?如果是这样,相对于ClassOne,解释器会更喜欢ClassTwo的方法/属性吗? 问题答案: 一个对象只能有一个原型。通过创建一个