多态是面向对象编程的基本原则,允许结构不同的对象实现相同的接口,因此可以互换工作。由于Python具有动态类型,多态的实现非常灵活。
在严格的静态类型语言(如Java、C++)中,多态的支持需要声明接口或抽象类。在Python中,由于鸭子类型,多态不绑定于继承层次结构甚至接口。关键在于对象应支持所需的方法/属性。
一方面,这使得语言灵活且方便。另一方面,也增加了运行时由于拼写错误或缺少所需方法而引发错误的可能性,这些错误在代码执行时才会显现。
在Python中区分:
class Animal: def speak(self): raise NotImplementedError class Dog(Animal): def speak(self): return 'Woof!' class Cat(Animal): def speak(self): return 'Meow!' def animal_voice(animal): print(animal.speak()) animal_voice(Dog()) # Woof! animal_voice(Cat()) # Meow!
class Duck: def quack(self): return 'Quack!' def make_quack(animal): print(animal.quack()) make_quack(Duck()) # Quack!
关键特征:
继承是Python中确保多态的唯一方式吗?
不是。由于鸭子类型,任何函数都可以接受具有所需方法的对象,而不限于其类或层次结构。
仅仅按照方法名称与签名的匹配是否可以算作多态,而不考虑其本质?
不是。如果对象支持所需的方法,但其语义与预期不同,可能会出现错误。多态只有在接口和含义都一致时才算成功。
抽象类是否能防止子类错误实现接口?
只能部分防止。如果子类未实现抽象方法,则在尝试创建实例时会引发TypeError。但如果实现有逻辑违规,仍可能出现错误。
在日志库中植入第三方类,该类有一个log()方法,但返回数据对象而不是写入日志。错误仅在使用时显现。
优点:
缺点:
类配备测试,通过抽象基类和@abstractmethod形式化接口,文档中规定了方法的语义。
优点:
缺点: