返回介绍

类通过继承进行定制

发布于 2024-01-29 22:24:15 字数 2252 浏览 0 评论 0 收藏 0

除了作为工厂来生成多个实例对象之外,类也可引入新组件(子类)来进行修改,而不对现有组件进行原地的修改。由类产生的实例对象会继承该类的属性。Python也可让类继承其他类,因而开启了编写类层次结构的大门,在阶层较低的地方覆盖现有的属性,让行为特定化。实际上,向层次的下端越深入,软件就会变得越特定。在这里和模块并不一致:模块的属性存在于一个单一、平坦的命名空间之内(这个命名空间不接受定制化)。

在Python中,实例从类中继承,而类继承于超类。以下是属性继承机制的核心观点。

·超类列在了类开头的括号中。要继承另一个类的属性,把该类列在class语句开头的括号中就可以了。含有继承的类称为子类,而子类所继承的类就是其超类。

·类从其超类中继承属性。就像实例继承其类中所定义的属性名一样,类也会继承其超类中定义的所有属性名称。当读取属性时,如果它不存在于子类中,Python会自动搜索这个属性。

·实例会继承所有可读取类的属性。每个实例会从创建它的类中获取变量名,此外,还有该类的超类。寻找变量名时,Python会检查实例,然后是它的类,最后是所有超类。

·每个object.attribute都会开启新的独立搜索。Python会对每个属性取出表达式进行对类树的独立搜索。这包括在class语句外对实例和类的引用(例如,X.attr),以及在类方法函数内对self实例参数属性的引用。方法中的每个self.attr表达式都会开启对self及其上层的类的attr属性的搜索。

·逻辑的修改是通过创建子类,而不是修改超类。在树中层次较低的子类中重新定义超类的变量名,子类就可取代并定制所继承的行为。

这种搜索的结果和主要目的就是,类支持了程序的分解和定制,比迄今为止所见到的其他任何语言工具都要好。另外,这样可以把程序的冗余度降到最低(减少维护成本),也就是把操作分解为单一、共享的实现。此外,这样写程序时,也可让我们对现有的程序代码进行定制,而不是在原地进行修改或是从头开始。

第二个例子

下个例子是建立在上一个例子基础之上的。首先,我们会定义一个新的类SecondClass,继承FirstClass所有变量名,并提供其自己的一个变量名。

SecondClass定义display方法以不同格式打印。定义一个和FirstClass中的属性同名的属性,SecondClass有效地取代其超类内的display属性。

回想一下,继承搜索会从实例往上进行,之后到子类,然后到超类,直到所找的属性名称首次出现为止。在这个例子中,因为SecondClass中的变量名display会在FirstClass内首先被找到,所以SecondClass覆盖了FirstClass中的display。有时候,我们把这种在树中较低处发生的重新定义的、取代属性的动作称为重载。

结果就是SecondClass改变了方法display的行为,把FirstClass特定化了。另外,SecondClass(以及其任何实例)依然会继承FirstClass的setdata方法。用一个例子来说明:

就像往常一样,我们调用Second Class创建了其实例对象。set data依然是执行FirstClass中的版本,但是这一次display属性是来自SecondClass,并打印定制的内容。图26-2描绘了其中涉及的命名空间。

图 26-2 在类树中较低的扩展类中重新定义变量名,从而覆盖了继承的变量名并将其专有化。在这里,SecondClass重新定义了方法display,从而定制了它的实例的display方法

这里有一件和OOP相关的很重要的事情要留意:Second Class引入的专有化完全是在FirstClass外部完成的。也就是说,不会影响当前存在的或未来的FirstClass对象,就像上一个例子中的x:

我们不是修改FirstClass,而是对它进行了定制。很自然,这是有意而为之的例子,但是作为一条规则,因为继承可以让我们像这样在外部组件内(也就是在子类内)进行修改,类所支持的扩展和重用通常比函数或模块更好。

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

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

发布评论

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