面向对象之多态
类的多态性
一:多态与多态性
多态指的是同一种事物有多种状态,比如动物的多种形态:猫,狗,猪,鸡。
class Animal: #同一类事物:动物
def talk(self):
pass
class Cat(Animal): #动物的形态之一:猫
def talk(self):
print('喵喵喵')
class Dog(Animal): #动物的形态之二:狗
def talk(self):
print('汪汪汪')
class Pig(Animal): #动物的形态之三:猪
def talk(self):
print('哼哼哼')
#实例化得到三个对象
>>> cat=Cat()
>>> dog=Dog()
>>> pig=Pig()
多态性指的是可以在不用考虑对象具体类型的情况下而直接使用对象,这就需要在设计时,把对象的使用方法统一成一种:例如cat、dog、pig都是动物,但凡是动物肯定有talk方法,于是我们可以不用考虑它们三者的具体是什么类型的动物,而直接使用
cat.talk() # 喵喵
dog.talk() # 旺旺
pig.talk() # 哼哼
定义一个统一的接口来进行访问
def Talk(animal):
animal.talk()
Talk(cat) # 喵喵
Talk(dog) # 旺旺
Talk(pig) # 哼哼
在pyton中一切皆对象,本身就是支持多态性
# 我们可以在不考虑三者类型的情况下直接使用统计三个对象的长度
str.__len__()
list.__len__()
tuple.__len__()
# Python内置了一个统一的接口
len(str)
len(list)
len(tuple)
多态性的好处在于增强了程序的灵活性和扩展性,比如通过继承Animal类创建了一个新的类,实例化得到的对象obj,可以使用相同方式使用obj.talk()
class Dog(Animal): # 动物猪
def talk(self):
print('哼哼哼哼')
dog = Dog() # 实例一头猪
dog.talk() # 使用者根本无需关心wolf是什么类型而调用talk
多态性的本质就是,在于不同的类中定义相同的方法名,这样我们就可以不考虑类,而统一使用一种方式使用对象,可以通过父类引入抽象类的概念来硬性规定限制子类,必须通过某些方法
import abc
# 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法
def talk(self): # 抽象方法中无需实现具体的功能
pass
class Cat(Animal): # 但凡继承Animal的子类都必须遵循Animal规定的标准
def talk(self):
pass
cat=Cat() # 若子类中没有一个名为talk的方法则会抛出异常TypeError,无法实例化
但其实我们完全可以不依赖于继承,只需要制造出外观和行为相同对象,同样可以实现不考虑对象类型而使用对象,这正是Python崇尚的“鸭子类型”(duck typing):“如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子”。比起继承的方式,鸭子类型在某种程度上实现了程序的松耦合度,如下
#二者看起来都像文件,因而就可以当文件一样去用,然而它们并没有直接的关系
class Txt: #Txt类有两个与文件类型同名的方法,即read和write
def read(self):
pass
def write(self):
pass
class Disk: #Disk类也有两个与文件类型同名的方法:read和write
def read(self):
pass
def write(self):
pass