支持协作多继承

 

本节不是关于来自多个Qt类的子类。

协作多继承是一种用于实现继承多个超类的类的技术 - 通常是主超类和一个或多个添加其他行为的mixin类。它可以在以后添加新的mixin以便进一步扩展行为,而无需更改类的实现或创建类实例的任何现有代码。

该技术要求所有超类的__init__方法遵循相同的模式,处理无法识别的关键字参数,并用于super()调用自己的超类__init__方法。

PyQt5的类遵循这种模式。

看Raymond Hettinger的Python超级()被认为超级!关于这个主题的一些更多背景的博客文章。

举个例子,假设我们有一个代表一个人的类,一个人有一个名字。以下可能是初始实现:

class Person(QObject):
    def __init__(self, name, parent=None)
        QObject.__init__(self, parent)

        self.name = name

通常可以通过以下方式之一创建实例:

person = Person("Joe")
person = Person("Joe", some_parent)

这种方法有一些局限性:

  • 仅公开QObject API 的子集。例如,您不能通过传递适当的关键字参数来设置Qt属性的值或连接信号Person.__init__
  • 将另一个类添加到Person超类列表中意味着__init__需要更改其 实现。如果新的mixin采用非可选参数,则每次创建Person实例的调用都需要更改。

考虑这个替代实现:

class Person(QObject):
    def __init__(self, name, **kwds):
        super().__init__(**kwds)

        self.name = name

不同之处在于我们只处理Person 类本身使用的参数,并通过调用将所有其他参数归入超类super()

通过此实现,通常可以通过以下方式之一创建实例:

person = Person("Joe")
person = Person("Joe", parent=some_parent)

这里的区别在于我们使用关键字参数来指定Person类本身未处理的任何参数。请注意,我们可以为所有参数使用关键字参数 - 无论您是否这样做都取决于个人选择。

第一次实施的限制不再适用。例如,如果没有任何进一步的更改,我们也可以这样做:

person = Person("Joe", destroyed=some_callable)

假设我们现在想Person通过添加一个处理一个人年龄的mixin 来扩展类的行为。mixin的实现如下:

class Age(object):
    def __init__(self, age=0, **kwds):
        super().__init__(**kwds)

        self.age = age

这遵循与我们的Person实现类似的模式,但请注意我们为age参数提供了默认值。

以下是我们的新Person实现:

class Person(QObject, Age):
    def __init__(self, name, **kwds):
        super().__init__(**kwds)

        self.name = name

我们必须做的唯一改变就是添加AgePerson超类的列表中。更重要的是,我们不需要更改任何调用来创建 Person实例。

如果我们确实想要创建一个Person非默认年龄的实例,那么我们只需将其作为关键字参数传递,如下所示:

person = Person("Joe", age=38)

这种技术增加了关键字参数的使用 - 虽然这意味着更多的输入,但它显着增加了应用程序代码的可读性。

猜你喜欢

转载自blog.csdn.net/Yuyh131/article/details/84648792
今日推荐