多态、多态性和鸭子类型
多态
多态指的是同一种事物有多种形态,比如水有液态、固态和气态。
一个抽象类有多个子类,因而多态的概念依赖于继承。
class Animal:
def talk(self):
pass
class Dog(Animal):
def talk(self):
print('汪汪汪')
class Cat(Animal):
def talk(self):
print('喵喵喵')
class Pig(Animal):
def talk(self):
print('哼哼哼')
dog = Dog()
cat = Cat()
pig = Pig()
多态性
多态性指的是可以在不用考虑对象具体类型的情况下而直接使用对象,这就需要在设计时,把对象的使用方法统一成一种:例如cat、dog、pig都是动物,但凡是动物肯定有talk方法,于是我们可以不用考虑它们三者的具体是什么类型的动物,而直接使用
dog.talk()
cat.talk()
pig.talk()
汪汪汪
喵喵喵
哼哼哼
更进一步,可以定义一个统一的接口来调用:
def Talk(obj):
obj.talk()
Talk(dog)
Talk(cat)
Talk(pig)
Python中的内置类型本身就支持多态性:
# 可以在不考虑类型的情况下使用同样的方法。
'str'.__len__()
[1,2,3].__len__()
{'k1':'v1','k2':'v2'}.__len__()
# 同样内置了一个统一的接口
len('str')
len([1,2,3])
len({'k1':'v1','k2':'v2'})
多态性的优点:
- 增加了程序的灵活性:以不变应万变,无论对象千变万化,使用者都是同一种形式去调用。
- 增加了程序的可扩展性:通过继承基类创建了新的类,使用者无需更改自己的代码,还是用相同的方式调用。
多态和多态性是不同的概念:
- 多态:在定义角度,同一种事物的多种形态,动物分为人类,猪类。
- 多态性:在调用阶段,同一种调用方式,不同的执行效果(多态性)
鸭子类型
字面意思指的是:如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子。
在代码中的意思是:只要类中有共同父类的属性和方法,就认为是同一个类。鸭子类型在某种程度上实现了松耦合度。
class Person: # Person就是鸭子
def run(self):
print('跑步技能')
class Coder: # Coder就可以当成Person类
def run(self):
print('跑路技能')
def work(self):
print('打工技能')
class Driver: # Driver也可以当成Person类
head = 1
def run(self):
print('开车技能')
Coder和Driver都拥有Person类的所有属性,即便Coder和Driver中各自又有自己的属性,它们依然能当做Person类。这样就可以不受父类约束从而也能达到多态性的目的。
多态必须是继承关系,子类必须将属性名和方法名及方法参数保持与父类一致(属性值和方法内代码可以不一样)。为了避免子类的属性名与父类不同,所以可以用abc模块进行限制。Python并不推荐使用abc模块限制,而更推荐使用鸭子态,但鸭子态容易失误写错属性名,所以我们还可以使用抛异常的方式进行限制命名。