多态

面向对象的三大特征:封装,继承,多态

封装:将数据和方法放在一个类里就构成了封装

继承: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()方法等方法;

原文地址:https://www.cnblogs.com/lzh501/p/10909055.html