Python爬虫、数据分析与可视化:工具详解与案例实战
上QQ阅读APP看书,第一时间看更新

3.3.4 多重继承与组合模式

Python语言支持多重继承,即一个子类可以同时继承多个父类,不过从项目实践角度来说多重继承会提升代码的维护成本,并很容易导致问题。在如下的MoreParentsDemo.py案例中,我们来观察一下多重继承带来的问题。


01 # coding=utf-8
02 class PrintByA3: # 打印的类,在A3纸上打印
03     def print(self):
04         print("Print File in A3.")
05 class PrintByA4: # 在A4纸上打印
06     def print(self):
07         print("Print File in A4.")
08 # 同时继承了两个类
09 # class PrintHandler(PrintByA4,PrintByA3):
10 class PrintHandler(PrintByA3,PrintByA4):
11     def handleFile(self):
12         print(self)
13 handler = PrintHandler()
14 handler.print()

在第2行和第5行里,我们分别定义了两个类,以实现在A3和A4纸上打印的功能,在其中的print方法里又分别输出了不同的语句。

在第10行的PrintHandler类里,我们分别继承了PrintByA3和PrintByA4这两个类,请注意继承的次序。在其中第11行的handleFile方法里,我们调用了父类的print方法。问题就在这里,两个父类都有print方法,这里究竟是继承了哪个?

运行上述代码,从第14行的打印语句中我们能看到“Print File in A3.”的输出,也就是说,实际继承了PrintByA3的print方法。如果这里打开第9行的注释,同时注释掉第10行的代码,让PrintHandler类继承两个类时变更继承的次序,就会看到“Print File in A4.”的输出。

从上述运行结果来看,多重继承时次序在前的类方法会覆盖掉之后的,这就会给使用带来困惑。在实际项目里,确实有类似的需求,比如在PrintHanlder类里需要同时具备在A3和A4纸上打印的功能,此时不建议用多重继承,而是建议使用组合。在如下的CompositionDemo.py代码里,我们将通过组合改善代码的结构。


01 # coding=utf-8
02 class PrintByA3: # 打印的类,在A3纸上打印
03     def print(self):
04         print("Print File in A3.")
05 class PrintByA4: # 在A4纸上打印
06     def print(self):
07         print("Print File in A4.")
08 class PrintHandler():
09     def __init__(self):
10         self.printByA3 = PrintByA3()
11         self.printByA4 = PrintByA4()
12     def handleFileAsA3(self):
13         self.printByA3.print()
14     def handleFileAsA4(self):
15         self.printByA4.print()
16 handler = PrintHandler()
17 handler.handleFileAsA3() # Print File in A3.
18 handler.handleFileAsA4() # Print File in A4.

在第2行和第5行定义的两个类里,我们同样实现了在A3和A4纸上打印两种功能。但是在第8行的PrintHandler类里,我们不再使用多重继承。

在第9行的__init__构造函数里,我们实例化了两个对象,在PrintHandler类里组合了两种打印的功能类,这样在第12行和第14行的两个方法里就能调用相关方法,实现不同方式的打印功能。从第17行和第18行的语句里,我们能看到组合的效果。

虽然以组合模式开发出的代码量比以多重继承要多,但是代码结构更为清晰,而且在使用的时候不会出现困惑。所以在使用继承特性时,如果出现两个父类具有相同的方法这种情况,就可以改用上述基于组合的实现模式。