zoukankan      html  css  js  c++  java
  • 流畅的python——12 继承的优缺点

    十二、继承的优缺点

    子类化内置类型很麻烦

    内置类型(使用 C 语言编写)不会调用用户定义的类覆盖的特殊方法。

    至于内置类型的子类覆盖的方法会不会隐式调用,CPython 没有制定官方规则。基本上,内置类型的方法不会调用子类覆盖的方法。例如,dict 的子类覆盖的 __getitem__() 方法不会被内置类型的 get() 方法调用。

    __setitem__ __getitem__ 方法:只有实例化子类对象,[] 运算符覆盖会生效

    直接子类化内置类型(如 dict、list 或 str)容易出错,因为内置类型的方法通常会忽略用户覆盖的方法。不要子类化内置类型,用户自己定义的类应该继承 collections 模块(http://docs.python.org/3/library/collections.html)中的类,例如 UserDict、UserList 和 UserString,这些类做了特殊设计,因此易于扩展。

    如果不子类化 dict,而是子类化 collections.UserDict,问题便迎刃而解了。

    了让实验版通过原始版的测试组件,还要实现 __init__、get 和 update 方法,因为继承自 dict 的版本拒绝与覆盖的 __missing____contains____setitem__ 方法合作。

    多重继承和方法解析顺序

    任何实现多重继承的语言都要处理潜在的命名冲突,这种冲突由不相关的祖先类实现同名方法引起。这种冲突称为“菱形问题”。

    (左)说明菱形问题UML 类图;(右)虚线箭头是示例 12-4 使用的方法解析顺序

    In [2]: class A:
       ...:     def pint(self):
       ...:         print('ping:',self)
       ...:
    
    In [7]: class C(A):
       ...:     def pont(self):
       ...:         print('pontCCC:',self)
       ...:
    
    In [8]: class B(A):
       ...:     def pont(self):
       ...:         print('pontBBB:',self)
       ...:
    
    In [6]: class D(B,C):
       ...:     def pint(self):
       ...:         super().pint()
       ...:         print('post-pint:', self)
       ...:     def pintpont(self):
       ...:         self.pint()
       ...:         super().pint()
       ...:         self.pont()
       ...:         super().pont()
       ...:         C.pont(self)
       ...:
    
    In [12]: d = D()
    
    In [13]: d.pont()
    pontBBB: <__main__.D object at 0x000001E89548D7F0>
    
    In [14]: C.pont(d)  # 显式调用
    pontCCC: <__main__.D object at 0x000001E89548D7F0>
    
    In [15]: d.pint()
    ping: <__main__.D object at 0x000001E89548D7F0>
    post-pint: <__main__.D object at 0x000001E89548D7F0>
    
    In [17]: D.__mro__  # 查找属性和方法 顺序 
    # 按照方法解析顺序列出各个超类,从当前类一直向上,直到 object 类。
    Out[17]: (__main__.D, __main__.B, __main__.C, __main__.A, object)
    

    注意,直接在类上调用实例方法时,必须显式传入 self 参数,因为这样访问的是未绑定方法(unbound method)。

    方法解析顺序不仅考虑继承图,还考虑子类声明中列出超类的顺序。也就是说,如果在 diamond.py 文件(见示例 12-4)中把 D 类声明为 class D(C, B):,那么 D 类的__mro__ 属性就会不一样:先搜索 C 类,再搜索 B 类。

    处理多重继承

    ……我们需要一种更好的、全新的继承理论(目前仍是如此)。例如,继承和实例化(一种继承方式)混淆了语用(比如为了节省空间而重构代码)和语义(用途太多了,比如特殊化、普遍化、形态,等等)。

    ​ ——Alan Kay

    ​ “The Early History of Smalltalk”

    如 Alan Kay 所言,继承有很多用途,而多重继承增加了可选方案和复杂度。使用多重继承容易得出令人费解和脆弱的设计。我们还没有完整的理论,下面是避免把类图搅乱的一些建议。

    多重继承,组合模糊,混入类

  • 相关阅读:
    jsp转向
    什么是 XDoclet?
    tomcat中的几点配置说明
    mysql5问题
    POJ 3734 Blocks
    POJ 2409 Let it Bead
    HDU 1171 Big Event in HDU
    POJ 3046 Ant Counting
    HDU 2082 找单词
    POJ 1286 Necklace of Beads
  • 原文地址:https://www.cnblogs.com/pythonwl/p/15508237.html
Copyright © 2011-2022 走看看