面向对象三大特性——多态(含鸭子类型)
一、多态概念
在面向对象编程中,接口的多种不同的实现方式即为多态。多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。
二、多态目的
多态的目的就是实现接口重用。
多态指的是一类事物有多种形态。比如动物有多种形态:人、狗、猪。
import abc #利用abc模块实现抽象类 class Animal(metaclass=abc.ABCMeta): # 类似接口,只定义规范,不实现具体的代码 @abc.abstractclassmethod def talk(self): pass class People(Animal): # 动物形态之一:人 def talk(self): print('people is talking') class Pig(Animal): # 动物形态之二:猪 def talk(self): print('Pig is talking') class Dog(Animal): # 动物形态之三:狗 def talk(self): print('Dog is talking')
三、多态性
1、多态性概念
多态性指在不考虑实例类型的情况下使用实例,多态性分为静态多态性和动态多态性。
静态多态性:就是在系统编译期间就可以确定程序执行到这里将要执行哪个函数
动态多态性:则是利用虚函数实现了运行时的多态,也就是说在系统编译的时候并不知道程序将要调用哪一个函数,只有在运行到这里的时候才能确定接下来会跳转到哪一个函数的栈帧。如下所示:
peo1 = People() pig1 = Pig() dog1 = Dog() # 调用方法不用考虑三者具体是什么类型直接使用,这种就是动态多态性 # peo1.talk() # pig1.talk() # dog1.talk() #更进一步,我们可以定义一个统一的接口来使用 def func(animal): animal.talk() func(peo1) func(pig1) func(dog1)
由上例可以看出,python本身就是支持多态性的。
2、多态性的好处
(1)增加程序的灵活性
以不变应万变,无论对象千变万化,使用者都是同一种形式去调用
(2)增加程序的扩展性
通过继承animal类创建一个新类,使用者可以不改变自己的代码,依然用func(animal)调用
>>> class Cat(Animal): #属于动物的另外一种形态:猫 ... def talk(self): ... print('say miao') ... >>> def func(animal): #对于使用者来说,自己的代码根本无需改动 ... animal.talk() ... >>> cat1=Cat() #实例出一只猫 >>> func(cat1) #甚至连调用方式也无需改变,就能调用猫的talk功能 say miao ''' 这样我们新增了一个形态Cat,由Cat类产生的实例cat1,使用者可以在完全不需要修改自己代码的情况下。
使用和人、狗、猪一样的方式调用cat1的talk方法,即func(cat1) '''
四、鸭子类型
什么是鸭子类型(Duck Typing)?鸭子类型可解释为,如果一只动物,走起来像鸭子或者叫起来像鸭子,就可以把它当作鸭子。
python崇尚一种鸭子类型,类与类之间不用共同继承一个父类,只需要将它们做得像一种事物即可。
例如,如果想编写现有对象的自定义版本。
1、可以继承该对象
2、可以创建一个外观和行为像,但与它无任何关系的全新对象(通常用于保存程序组件的松耦合度)
例1:利用标准库中定义的各种‘与文件类似’的对象,尽管这些对象的工作方式像文件,但他们没有继承内置文件对象的方法
class File: def read(self): pass def write(self): pass class Disk: def read(self): print('disk read') def write(self): print('disk write') class Text: def read(self): print('text read') def write(self): print('text write') disk = Disk() text = Text() disk.read() disk.write() text.read() text.write() """ disk read disk write text read text write """
例2:序列类型有多种形态:字符串,列表,元组,但他们直接没有直接的继承关系
# 序列类型:列表list、元组tuple、字符串str l = list([1, 2, 3]) t = tuple(('a', 'b')) s = str('hello') print(l.__len__()) # 3 print(t.__len__()) # 2 print(s.__len__()) # 5