多态
面向对象的三大特征:封装,继承,多态
封装:将数据和方法放在一个类里就构成了封装
继承:Python中一个类可以继承于一个类,也可继承多个类,被继承的类叫做父类(或者叫基类 base class),继承的类叫子类
多态:指的是一类事物有多种形态,一个抽象类有多个子类(因而多态的概念依赖于继承),不同的子类对象调用相同的方法,产生不同的执行结果,多态可以增加代码的灵活度
***Python中函数的参数没有类型限制,因此调用函数时不管传什么类型的参数都是可行的
***Python中没有真正的多态,只有伪多态
多态
实现多态的步骤:
1、定义一个父类(base),实现某个方法(如:run)
2、定义多个子类,在子类中重写父类的方法(run),每个子类的run方法实现不同的功能
3、假设定义了一个函数,需要一个base类型的的对象的参数,那么调用函数的时候,传入base类不同的子类对象,那么这个函数就会执行不同的功能,这就是多态的体现
class Animal(object): def run(self): print("------base-----走路") class Cat(Animal): def run(self): print("-------cat-------爬树") class Dog(Animal): def run(self): print("--------dog-------会跑") class Pig(Animal): pass a_obj = Animal() c_obj = Cat() d_obj = Dog() p_obj = Pig() print(isinstance(c_obj,Animal)) # 打印出来是True,说明子类创建的对象属于父类的类型 def func(base_obj): # 假设func函数里传的参数为Animal类型的,那么Animal子类创建的对象也能够调用里面的函数 base_obj.run() func(a_obj) func(c_obj) func(d_obj) func(p_obj) 执行结果为: True ------> 是print(isinstance(c_obj,Animal))执行的结果 ------base-----走路 -------cat-------爬树 --------dog-------会跑 ------base-----走路
在Python中,只要有一个类实现了run方法,那么就可调用上面例子中的func函数,因此称做伪多态----也叫鸭子类型;
如:
def func(base_obj): # 假设func函数里传的参数为Animal类型的,那么Animal子类创建的对象也能够调用里面的函数 base_obj.run() class MyAnimal(object): def run(self): print("----会睡觉---") ma = MyAnimal() func(ma) 执行结果为: ----会睡觉---
***Python中的鸭子类型:它并不要求严格的继承体系,关注的不是对象的类型本身,而是,它是如何使用的,一个对象只要”看起来像鸭子,走起路来像鸭子“,
那它就可以被看成鸭子;
***鸭子类型的体现:
静态语言:对于静态语言(java/c#)来讲,上面传入的对象必须是Animal类型或者它的子类,否则将无法调用run()方法;
动态语言:对于动态语言Python来讲,上面传入的并不一定要是Animal类型,也可以是其他类型,只要其在内部实现了run()方法就行了;
多态的意义:
开放封闭原则:
对于一个变量,我们只需知道它是Animal类型,无需确切的知道它的子类型,就可以放心的调用run()方法(调用方只管调用,不管细节);
当需要新增功能,只需要新增一个Animal的子类实现run()方法,就可以在原来的基础上进行功能扩展,这就是著名的开放封闭原则;
对扩展开放:运行新增Animal子类;
对修改封闭:不需要修改依赖Animal类型的run()方法等方法;