多态:由于子类不同,同一个方法名产生的行为不同。
例如:多媒体,想让它实现一行为,但是不知道是什么类型的多媒体。现在有MP3等设备,都有各自运行行为play这个方法,他们继承了多媒体这个类,然后编写属于自己的play方法于是,实现了不同子类的同一方法名的不同行为。
class AudioFile:
"定义一个多媒体类"
def __init__(self,filename):
if not filename.endswith(self.ext):
"这里的filename是形参filename"
"""因为子类父类没有同名方法和属性,在实例化子类同时通是父类和子类整体在实例化,
因此子类中的属性方法和父类中属性方法是同级别的,既然是同级别的就可以调用整体自身
的属性和和方法。在这里表现为ext属性即self.ext"""
raise Exception("Inalid file format")
self.filename=filename
"把形参filename的值传给实例属性filename"
class MP3File(AudioFile):
ext ="mp3"
def play(self):
"mps的play方法"
print("Play {} as mp3".format(self.filename))
class OggFile(AudioFile):
ext ="ogg"
def play(self):
"ogg的play方法"
print("Play {} as Ogg".format(self.filename))
ogg=OggFile("houre.ogg")
ogg.play()
mps=MP3File("loser.mp3")
mps.play()
Play houre.ogg as Ogg
Play loser.mp3 as mp3
鸭子类型:
如果它走像鸭子,游泳像鸭子,那么就是只鸭子
我们不关心它是否真的是一只鸭子(继承自动物类的鸭子),因为静态面向对象的语言定义一个鸭子通可以需要首先它应该是动物,然后它应该是动物里的两栖类,最后它才是鸭子,所以需要继承父类,最后才能表达自己。但是动态语言python它只关心会游泳走路就好了,不继承也无所谓。
例如:
class FlacFile:
def __init__(self,filename):
if not filename.endswith(".flac"):
raise Exception("Invaild file format")
self.filename=filename
def play(self):
print("Playing {} as flac".format(self.filename))
这个类依然可以实现play方法,但是它没有继承多媒体类AudioFile,那么它究竟是不是一个flac无所谓,也不关心,只要它能实现我们想要的play运行方法就可以了。
a=FlacFile("happy.flac")
a.play()
Playing happy.flac as flac
多态实际上是面向对象编程中非常酷的概念之一,不同子类通过对同一父类继承实现了不同子类同一方法的不同行为,但是鸭子类型让多态不那么酷了,它可以不用是继承自什么类,究竟是什么,同样可以实现目的。在某种意义上python的多态大多指的是鸭子类。