返回介绍

12.3 多重继承的真实应用

发布于 2024-02-05 21:59:47 字数 2333 浏览 0 评论 0 收藏 0

多重继承能发挥积极作用。《设计模式:可复用面向对象软件的基础》一书中的适配器模式用的就是多重继承,因此使用多重继承肯定没有错(那本书中的其他 22 个设计模式都使用单继承,因此多重继承显然不是灵丹妙药)。

在 Python 标准库中,最常使用多重继承的是 collections.abc 包。这没什么问题,毕竟连 Java 都支持接口的多重继承,而抽象基类就是接口声明,只不过它可以提供具体方法的实现。5

5前面说过,Java 8 也允许提供方法实现。这个新功能在官方的 Java 教程中叫默认方法

在标准库中,GUI 工具包 Tkinter(tkinter 模块是 Tcl/Tk 的 Python 接口,https://docs.python.org/3/library/tkinter.html)把多重继承用到了极致。图 12-2 中展示的方法解析顺序是 Tkinter 小组件层次结构的一部分,图 12-3 则列出了 tkinter 基包中的全部小组件类(tkinter.ttk 子包中还有一些,https://docs.python.org/3/library/tkinter.ttk.html)。

图 12-3:Tkinter GUI 类层次结构的 UML 简图;使用 «mixin» 标记的类通过多重继承为其他类提供具体方法

写作本书时,Tkinter 已经 20 岁了,不能代表当下的最佳实践。但是,它却能表明当没有意识到多重继承的缺点时,程序员是如何使用多重继承的。下一节讨论一些好的做法时,会把 Tkinter 作为反面教材。

来看图 12-3 中的几个类。

❶ Toplevel:表示 Tkinter 应用程序中顶层窗口的类。

❷ Widget:窗口中所有可见对象的超类。

❸ Button:普通的按钮小组件。

❹ Entry:单行可编辑文本字段。

❺ Text:多行可编辑文本字段。

这几个类的方法解析顺序如下,这些输出使用示例 12-8 中定义的 print_mro 函数得到:

>>> import tkinter
>>> print_mro(tkinter.Toplevel)
Toplevel, BaseWidget, Misc, Wm, object
>>> print_mro(tkinter.Widget)
Widget, BaseWidget, Misc, Pack, Place, Grid, object
>>> print_mro(tkinter.Button)
Button, Widget, BaseWidget, Misc, Pack, Place, Grid, object
>>> print_mro(tkinter.Entry)
Entry, Widget, BaseWidget, Misc, Pack, Place, Grid, XView, object
>>> print_mro(tkinter.Text)
Text, Widget, BaseWidget, Misc, Pack, Place, Grid, XView, YView, object

在类之间的关系方面有几点要注意。

Toplevel 是所有图形类中唯一没有继承 Widget 的,因为它是顶层窗口,行为不像小组件,例如不能依附到窗口或窗体上。Toplevel 继承自 Wm,后者提供直接访问宿主窗口管理器的函数,例如设置窗口标题和配置窗口边框。

Widget 直接继承自 BaseWidget,还继承了 Pack、Place 和 Grid。后三个类是几何管理器,负责在窗口或窗体中排布小组件。各个类封装了不同的布局策略和小组件位置 API。

Button 与大多数小组件一样,只是 Widget 的子代,也间接继承 Misc,后者为各个小组件提供了大量方法。

Entry 是 Widget 和 XView 的子类,后者实现横向滚动。

Text 是 Widget、XView 和 YView 的子类,后者提供纵向滚动功能。

下面将讨论多重继承一些好的做法,看看 Tkinter 有没有践行。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文