OOP-多态
- 多态在python中不是语法,是一种思想因为python本身就是一个多态语言(万物皆对象): 多个不同类的对象,都具有一些共同的特性,这些对象中的任何一个对象,都可以调用这些共同的特性,但是,因为是不同类的对象,所以,在调用同一个特性时,会表现出不同的行为
- 同一个对象在不同情况下有不同的状态出现
- 一种调用方式,可以有不同的调用结果
- 多态能够提高代码的复用性,让代码更加精简易读,并且降低了代码的耦合度(紧密配合与相互影响的程度),提升了代码的扩展性
demo1¶
- 常见的我们经常使用的count()方法就是多态特性
obj = '小宇棒,小宇帅,小宇好厉害!' # 变量引用字符串对象
print(obj.count('小宇')) # 显示输出结果为:3
obj = ('小宇', '樱井', '小宇', '明步') # 变量引用元组对象
print(obj.count('小宇')) # 显示输出结果为:2
- 上方代码中,“obj”就是多态对象,它可以是不同的对象,我们不管"obj"是什么对象(字符串或元组或其它),我们只需要这个"obj"有count()这个attribute,如果有这个方法,那就能做处理.但是,虽然调用的方法都是同一个名称,因为处理的是不同的对象,实际上具体的处理行为是不一样的.
demo2¶
- 这里找了一个很不错的例子,可以说明多态带来的特性以及优势
- 比如一个动物园的饲养员,需要喂养老虎,狮子,以及狗熊
先做非多态处理
# 定义动物
class Lion: # 定义狮子类
def lion_eat(self): # 定义进食函数
print('狮子在吃东西!')
class Tiger: # 定义老虎类
def tiger_eat(self): # 定义进食函数
print('老虎在吃东西!')
class Bear: # 定义狗熊类
def bear_eat(self): # 定义进食函数
print('狗熊在吃东西!')
# 定义饲养员
class Feeder:
def feed_lion(self, lion): # 定义喂养狮子的函数
lion.lion_eat()
def feed_tiger(self, tiger): # 定义喂养老虎的函数
tiger.tiger_eat()
def feed_bear(self, bear): # 定义喂养猴子的函数
bear.bear_eat()
# 喂养过程
feeder = Feeder()
lion = Lion()
feeder.feed_lion(lion) # 显示输出结果为:狮子在吃东西!
tiger = Tiger()
feeder.feed_tiger(tiger) # 显示输出结果为:老虎在吃东西!
bear = Bear()
feeder.feed_bear(bear) # 显示输出结果为:狗熊在吃东西!
上方的代码虽然正常,但是如果动物园突然多了一只猴子需要喂养(/滑稽),那么就再增加一些代码
#定义动物
class Monkey:
def monkey_eat(self):
print('猴子在吃东西!')
#定义饲养员
class Feeder:
...
def feed_monkey(self, monkey):
monke.monkey_eat()
...
# 喂养过程
monkey = Monkey()
feeder.feed_monkey(monkey)
但是这样又凸显一个问题,如果动物源源不断的每天都增加,那么每天都要写很多代码(给饲养员增加代码,添加动物代码)来适应不同的动物进行喂食,
多态处理
class Lion: # 定义狮子类
def eat(self): # 定义进食函数
print('狮子在吃东西!')
class Tiger: # 定义老虎类
def eat(self): # 定义进食函数
print('老虎在吃东西!')
class Bear: # 定义狗熊类
def eat(self): # 定义进食函数
print('狗熊在吃东西!')
class Feeder: # 定义饲养员类
def feed_animal(self, animal): # 定义喂食方法
animal.eat()
# 喂养过程
feeder = Feeder()
animal = Lion()
feeder.feed_animal(animal) # 显示输出结果为:我是狮子,在吃东西!
animal = Tiger()
feeder.feed_animal(animal) # 显示输出结果为:我是狮子,在吃东西!
animal = Bear()
feeder.feed_animal(animal) # 显示输出结果为:我是狗熊,在吃东西!
- 在代码中规范了喂食的接口, 统一了喂食动作的命名,这样,多个类中都有一个相同的特性(eat方法)实例对象也就具有了这个相同的(eat方法)所以,不管调用的时候是哪一种实例对象(变量animal)都可以调用这个特性(eat方法),但是因为调用这个特性的实例对象(变量animal)不同,所以产生的行为(eat方法的处理过程)是不同的
- 如果增加新的动物,那也只需要增加新的动物种类,以及喂养过程中对动物的实例化和调用喂养方法
#定义动物
class Monkey:
def eat(self):
print('猴子在吃东西!')
# 喂养过程
animal = Monkey()
feeder.feed_animal(animal)
- 从这个示例我们也能够看出,喂食方法无需再重复定义,多喂养一种动物只需要定义一个新的类