阿里云【名师课堂】Java面向对象开发64:多态性
基本概念
代码的重用不是全部靠继承实现,还有另一个重要的核心概念:多态性。
Java中对多态的核心表现主要有以下两点:
- 方法的多态性
- 方法的重载:同一个方法名称,可以根据参数的类型及个数的不同调用不同的方法体;
- 方法的覆写:同一个父类方法,可能根据实例化子类的不同也有不同的实现;
- 对象的多态性(前提:方法覆写):
- (自动、常用)对象的向上转型:
父类 父类对象 = 子类实例 ;
- (强制)对象的向下转型:
子类 子类对象 = (子类)父类实例 ;
- 对象的多态性说白了就是对象在子类和父类之间的转换。
- (自动、常用)对象的向上转型:
对象的多态性
上转型
范例:实现向上转型
class Person {
public void printInfo() {
System.out.println("【Person类】printInfo()方法") ;
}
}
class Student extends Person {
public void printInfo() {
System.out.println("【Student类】printInfo()方法") ;
}
}
public class TestDemo {
public static void main(String args[]) {
Student stu = new Student() ; // 子类实例化对象,放入子类中
stu.printInfo();
Person per = new Student() ; // 子类实例化对象,放入父类中,上转型
per.printInfo();
}
}
理解:父类虽然穿在身,心依然是子类心
- 上转型对象可以访问子类继承或隐藏的成员变量,也可以调用子类继承或重写的方法,不可以调用子类自己定义的方法。
注意:不管是否发生上转型,关注的重点应该是:
- 哪个类创建了新对象(new在哪里)
- 调用的方法是否被子类覆写
下转型
下转型指的是将父类对象转换为子类对象,但是在此之前需要首先明确一个概念:为什么需要下转型?
- 当需要使用到子类扩充的方法操作时需要下转型。
class Person {
public void printInfo() {
System.out.println("【Person类】printInfo()方法") ;
}
}
class Student extends Person {
public void printInfo() {
System.out.println("【Student类】printInfo()方法") ;
}
public void printMsg() { // 该方法是子类自身扩充的
System.out.println("【Student类】printMsg()方法") ;
}
}
public class TestDemo {
public static void main(String args[]) {
Student stu = new Student() ; // 子类实例化对象,放入子类中
stu.printInfo();
Person per = new Student() ; // 子类实例化对象,放入父类中,上转型
per.printInfo(); // 这时per能调用的只有父类定义过的方法(其实调用的是被子类继承or重写之后的)
// per不能调用子类自身定义的方法,只有下转型之后可以
Student stuA = (Student)per ;
stuA.printMsg() ;
}
}
注意:并不是所有的父类对象给都可以进行下转型:
- 如果想要进行下转型,一定要先进行上转型,上转型之后的对象才可以下转型给子类。
- 范例:观察错误代码
public class TestDemo {
public static void main(String args[]) {
Person per = new Person() ; // 父类实例化对象
Student stuA = (Student)per ; // 直接下转型
stuA.printMsg() ;
}
}
报错:java.lang.ClassCastException: Person cannot be cast to Student
理解:父类是渣男,并不知道自己有多少子类,换句话说,不知道这些类和自己的关系;而子类都知道自己是继承父类的。所以可以由子➡父➡子
,不可以直接父➡子
。
instanceof关键字
既然下转型存在隐患,那么怎么转型才靠谱呢?最好的做法是先进行判断,使用instanceof
关键字。
实际上instanceof是一个二目运算符,返回的是boolean型数据,使用格式为:
子类对象 instanceof 类
范例:观察instanceof关键字
public class TestDemo {
public static void main(String args[]) {
Person perA = new Student() ;
Person perB = new Person() ;
System.out.println(perA instanceof Person) ;
System.out.println(perA instanceof Student) ;
System.out.println(perB instanceof Person) ;
System.out.println(perB instanceof Student) ;
}
}
范例:下转型前的判断
public class TestDemo {
public static void main(String args[]) {
Person perA = new Student() ;
if (perA instanceof Student) {
Student stuA = (Student)perA ;
stuA.printMsg() ;
}
}
}
具体应用
范例:要求定义一个方法,这个方法可以接收父类的所有子类实例,并调用父类的方法
class Person {
public void eat() {
System.out.println("吃饭...") ;
}
}
class Student extends Person {
public void eat() {
System.out.println("【Student】在学校食堂") ;
}
}
class Professor extends Person {
public void eat() {
System.out.println("【Professor】在校外餐厅") ;
}
}
public class TestDemo {
public static void main(String args[]) {
hunger(new Person()) ;
hunger(new Student()) ;
hunger(new Professor()) ;
}
public static void hunger(Person per) { // 这里传入的参数就运用了对象多态性
per.eat() ; // 所有人都吃,不管哪一类
}
}
/*
这里对象多态性的工作原理:
Person per = new Person() ; 创建父类对象,调用父类的eat方法
Person per = new Student() ; 对象自动上转型,调用子类继承父类的eat方法
Person per = new Professor() ; 对象自动上转型,调用子类继承父类的eat方法
如果不用对象多态性,就要多次使用方法重载,变成:
public static void hunger(Student per) {}
public static void hunger(Professor per) {}
······
*/
通过程序,可以看出对象上转型的核心功能:操作参数统一。
总结
- 对象多态性实现的核心在于方法的覆写。
- 通过对象的上转型可以实现接收参数的统一,而向下转型可以实现子类扩充方法的调用(比较少用到);
- 两个没有关系的对象是不能进行转型的,所以下转型是存在安全隐患的。
目前还是不适应博客园的界面,等学成了再回归吧,对我来说当下还是csdn比较方便快捷:https://blog.csdn.net/weixin_43624945