什么是多态?
多态是类在继承关系下的一种形态,是同一方法对不同的子类对象所产生的不同的形态。
下边先通过一个案列来了解多态的现象:
案例:一个在线教育学习平台,有一个具体的功能需求:当学员登录后系统需要根据学员的类型获取他的服务权限,比如:对于普通学生他可以自学课程、下载资源、在线问答,对于Vip学生还可以额外有专属老师指导、专属交流群等 Vip服务,如何使用面向对象的编程思想实现这一功能需求?
分析:我们使用继承关系实现上述案例,可以定义一个学生基础类(PbStudent),定义普通学生类(OrdStudent)和Vip学生类(VipStudent)继承学生基础类,然后分别在两个子类中重写获取服务内容的方法StudentService(),最后在主控类(PbMain)中进行调用实现。如下:
学生基础类:
package Class.Object.Object03_Polymorphic.demo_01;
public class PbStudent {
public void StudentService(){
}
}
普通学生类:
package Class.Object.Object03_Polymorphic.demo_01;
public class OrdStudent extends PbStudent{
//重写父类的StudentService方法
@Override
public void StudentService() {
System.out.println("-----普通学生-----");
System.out.println("自学课程");
System.out.println("下载资源");
System.out.println("在线问答");
}
}
Vip学生类:
package Class.Object.Object03_Polymorphic.demo_01;
public class VipStudent extends PbStudent{
//重写父类的StudentService方法
@Override
public void StudentService() {
System.out.println("-----Vip学生-----");
System.out.println("自学课程");
System.out.println("下载资源");
System.out.println("在线问答");
System.out.println("专属老师指导");
System.out.println("专属交流群");
}
}
主控类:
package Class.Object.Object03_Polymorphic.demo_01;
public class PbMain {
//获取学生权限
public static void getStudentService(PbStudent student){
//调用StudentService方法
student.StudentService();
}
public static void main(String[] args) {
//创建普通学生对象
OrdStudent ordStudent = new OrdStudent();
//调用getStudentService方法,并传递ordStudent对象
getStudentService(ordStudent); //向上转型
//创建Vip学生对象
VipStudent vipStudent = new VipStudent();
//调用getStudentService方法,并传递vipStudent对象
getStudentService(vipStudent);
}
}
结果:
注:调用的就是同一个student.getStudentService();方法。getStudentService方法接收PbStudent的子类型,当传入OrdStudent对象则查询普通学生对象的服务内容,当传入VipStudent对象则查询 Vip学生的服务内容。应证了同一方法对不同的子类对象所产生的不同的形态。
向上转型和动态绑定
向上转型和动态绑定时多态最重要的特性和实现原理。
1.向上转型
上述例子中OrdStudent类和VipStudent类是PbStudent的子类,下图红框中将子类对象地址赋值给父类引用,public static void getStudentService(PbStudent student)方法接受了不同子类的对象地址,简单来说就是将子类类型转换为父类类型进行使用。这就是向上转型。
2.动态绑定
1) 第一张图主控类中,红框显示这里代码显示是调用父类的StudentService方法;但从第二张图可以看出父类中该方法为空。
能执行输出内容的原因是因为:执行的时候调用的子类的StudentService方法, 这就是动态绑定.
2) 动态绑定是运行
时发生的(而不是在编译的时候),在运行的时候会找到父类引用所指向的子类对象的真正类型
,然后会调用该类型中的方法。
静态绑定:
动态绑定是在运行的时候才确定类型
,静态绑定是在编译的时候就确定类型
。
在继承关系中,子类无法重写的方法就是静态绑定方法,比如:static方法、final方法、private方法等。
总结:怎么实现一个多态?
1.需要有继承关系,并且在子类中实现方法重写;
2. 构造子类对象,并赋值给父类引用变量(向上转型);
3. 调用父类的方法,根据父类引用变量指向的对象,找到具体子类的方法进行调用(动态绑定)。