面向对象之多态与多态性
一、多态
1、定义:指的是一类事物的多种形态,如水有液体、气体和固体三种形态, 动物有人、猫、狗等存在形态。
2、示例:
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
import abc
class Animal(metaclass=abc.ABCMeta): # 同一类事物
@abc.abstractmethod
def eat(self):
pass
class People(Animal): # 动物形态一:人
def eat(self):
print('people is eating')
class Dog(Animal): # 动物形态二:狗
def eat(self):
print('dog is eating')
class Cat(Animal): # 动物形态三:猫
def eat(self):
print('cat is eating')
person = People()
dog = Dog()
cat = Cat()
二、多态性
1、定义:指的是可以在不考虑对象的类型的情况下而直接使用对象。
2、多态性的类型可分为静态多态性和动态多态性。
静态多态性:任何类型都可以用运算符+进行运算。
动态多态性(通过示例来说明)
person = People()
dog = Dog()
cat = Cat()
#person、dog、cat都是动物,所以是动物肯定有eat方法
# 于是我们可以不用考虑它们三者的具体是什么类型,而可以直接使用
person.eat()
dog.eat()
cat.eat()
# 因此,更近一步,我们可以定义一个统一的接口来使用
# 动物类的通用方法,而不需要区分动物的形态种类,比如学开车,学了一种车,可以开奥迪、宝马等其他车,而不需要每个单独学
def func(animal):
animal.eat()
func(person)
3、多态性的好处
1、增加了程序的灵活性,以不变应万变,不论对象怎么变化,使用者都以同一种形式去调用,比如:func(animal)
2、增加了程序的可扩展性,比如通过继承Animal类,使用者无需更改自己的代码,还是用func(animal)去调用
# 通过继承Animal类创建一个新的类,使用者无需更改自身代码,仍然使用func(person)去调用
class Bird(Animal): # 属于动物的另一种形态:鸟
def eat(self):
print("I'm eating")
def func(animal): #对于使用者而言,自身代码无需更改
animal.eat()
bird1 = Bird() # 实例出一只鸟
func(bird1) # 调用方式也无需改变,就能调用鸟的eat功能
'''
这样我们新增了一个形态Bird,由Bird类产生的实例Bird1,使用者可以在完全不需要修改自己代码的情况下。使用和人、狗、猫一样的方式调用bird1的eat方法,即func(bird1)
'''
三、鸭子类型
1、鸭子类型:Python崇尚鸭子类型,即“如果看起来像,叫声像,而且走起路来像鸭子,那么它就是鸭子。”
实例1:
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
class Textfile:
def read(self):
print('reading')
def write(self):
print('writing')
class Diskfile:
def read(self):
print('reading')
def write(self):
print('writing')
textfile = Textfile()
textfile.read()
diskfile = Diskfile()
diskfile.read()
注意:尽管Textfile类和Diskfile类都没有继承内置文件对象的方法,但Textfile和Diskfile看起来都像是文件,因而都可以当作文件一样使用文件的read方法。
示例2:
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# list、tuple、str都是序列类型
l = list([1,2,3])
t = tuple(('h','y','s','t'))
s = str('ht514')
# 使用内置方法
print(l.__len__()) # 3
print(t.__len__()) # 4
print(s.__len__()) # 5
# 等同于下列自定义调用方法
def len(func):
return func.__len__()
print(len(l)) # 3
print(len(t)) # 4
print(len(s)) # 5
# list、tuple、str没有继承同一个父类,但看起来都像序列,就都可以调用__len__()方法
读书原为修身,正己才能正人正世;不修身不正己而去正人正世者,无一不是盗名欺世;你把念过的书能用上十之一二,就是很了不得的人了。——朱先生