面向对象--多态
一、前言
多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话,对不同类的对象发出相同的消息将会有不同的行为。
多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定。
二、多态
一个抽象类具有多个子类,就是多种形态。多态依赖于继承,没有继承就没有多态。
1 class Animal(object): 2 3 def __init__(self, name, age): 4 self.name = name 5 self.age = age 6 pass 7 8 9 class Dog(Animal): 10 11 def __init__(self, name, age, breed): 12 super(Dog, self).__init__(name, age) 13 self.breed = breed 14 pass 15 16 17 class Cat(Animal): 18 19 def __init__(self, name, age, breed): 20 super(Cat, self).__init__(name, age) 21 self.breed = breed 22 pass
我们定义了一个 Animal类,又定义了其两个子类 :Dog 和 Cat。这两个子类就表示了Animal这个类的多种形态。
三、多态性
多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。
1 class Person(object): 2 def __init__(self, name, age, gender): 3 self.name = name 4 self.age = age 5 self.gender = gender 6 7 def identity(self): 8 return 'I am a Person, my name is %s' % self.name 9 10 11 class Student(Person): 12 def __init__(self, name, age, gender, score): 13 super(Student, self).__init__(name, age, gender) 14 self.score = score 15 16 def identity(self): 17 return 'I am a Student, my name is %s' % self.name 18 19 20 class Teacher(Person): 21 def __init__(self, name, age, gender, course): 22 super(Teacher, self).__init__(name, age, gender) 23 self.course = course 24 25 def identity(self): 26 return 'I am a Teacher, my name is %s' % self.name 27 28 29 def identical(x): 30 return x.identity() 31 32 p = Person('Tim', 22, 'FM') 33 s = Student('bigberg', 22, 'M', 88) 34 t = Teacher('Luodao', 44, 'M', 'python') 35 36 print(identical(p)) 37 print(identical(s)) 38 print(identical(t))
#运行结果 I am a Person, my name is Tim I am a Student, my name is bigberg I am a Teacher, my name is Luodao
方法调用将作用在 x 的实际类型上。s 是Student类型,它实际上拥有自己的 identity()方法以及从 Person继承的 identity()方法,但调用 s.identify()总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止。
由于Python是动态语言,所以,传递给函数 identical(x)的参数 x 不一定是 Person 或 Person 的子类型。任何数据类型的实例都可以,只要它有一个identity()的方法即可:
class Book(object): def identity(self): return 'I am a book.' print(identical(b)) # 结果 I am a book
这是动态语言和静态语言(例如Java)最大的差别之一。动态语言调用实例方法,不检查类型,只要方法存在,参数正确,就可以调用。