面向对象编程三大机制,继承、封装、多态。今天大家一起来Java和Python的多态,简单来说,多态是指,针对某个类型的方法调用,其真正执行的方法取决于运行时期实际类型的方法。这话说起来不一定太好理解,大家先理清一个概念:覆写(Override)。
一、Java覆写(Override)
在继承关系中,子类如果定义了一个与父类方法签名完全相同的方法,被称为覆写(Override)。还是照旧先举个栗子:
class Person {
public void hello() {
System.out.println("Hello,Person!");
}
}
如上代码可见,在Person类中,定义了一个hello()方法,当调用它的时候,打印输出"Hello,Person!"。
接下来在Person的子类Student类中,也定义一个hello()方法,当调用它的时候,打印输出"Hello,Student!"。
class Student extends Person {
public void hello() {
System.out.println("Hello,Student!");
}
}
如上代码,子类Student中也定义了一个与父类Person类中相同名称、相同返回值类型且相同参数的方法(Override)。
二、Java多态
在之前的公众号文章中,已经给大家讲过,引用变量的声明类型可能与其实际类型不符,例如按如下方式定义对象p:
Person p = new Student();
现在,大家考虑上面刚才说的这种情况,如果子类的hello()(Override)覆写了父类的方法hello(),当调用p.hello()时,应该打印"Hello,Person!"还是"Hello,Student!"?
public class Java2 {
public static void main(String[] args) {
Person p = new Student();
p.hello(); //应该打印"Hello,Person!"还是"Hello,Student!"?
}
}
class Person {
public void hello() {
System.out.println("Hello,Person!");
}
}
class Student extends Person {
public void hello() {
System.out.println("Hello,Student!");
}
}
Java结果如下:
运行上面的代码,得到结果:"Hello,Student!"。实际上调用的方法是Student的hello()方法。因此可得出结论:
Java的实例方法调用是基于运行时的实际类型的动态调用,而非变量的声明类型。这个非常重要的特性在面向对象编程中称之为多态。它的英文拼写非常复杂:Polymorphic。
所以,多态的特性就是,运行期才能动态决定调用的子类方法。对某个类型调用某个方法,执行的实际方法可能是某个子类的覆写方法。
三、Python多态
与C++、Java一样,Python中也支持多态,但是是有限的的支持多态性,主要是因为Python中变量的使用不需要声明,所以不存在父类引用指向子类对象的多态体现,同时python不支持重载。在Python中 多态的使用不如Java中那么明显,所以Python中刻意谈到多态的意义不是特别大。
大家先来看一个栗子,先写了一个父类Parent及父类的__init__构造函数,然后写了一个子类Child继承父类Parent,也写了子类的__init__构造函数:
class Person(object):
def __init__(self, name):
self.name = name
def whoAmI(self):
print('I am a Person, my name is %s' % self.name)
#子类继承父类,并覆写 whoAmI方法
class Student(Person):
def __init__(self,name):
self.name = name
def whoAmI(self):
print('I am a Student, my name is %s' % self.name)
接下来,将父类Person和子类Student分别实例化,并调用各自的whoAmI方法,看看输出的是什么结果:
#将父类实例化,并调用父类的whoAmI方法
p = Person('weiwei')
p.whoAmI()
#将子类实例化,并调用子类的whoAmI方法
s = Student('weiwei')
s.whoAmI()
Python结果如下:
如上图所示的输出结果,不难看出,父类对象p调用的是父类的whoAmI方法,子类对象s调用的是子类的whoAmI方法。这种行为称为多态。也就是说,方法调用将作用在对象的实际类型上。s 是Student类型,它实际上拥有自己的 whoAmI()方法以及从 Person继承的 whoAmI方法,但调用 s.whoAmI()总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止。
发表评论 取消回复