阿里云【名师课堂】Java面向对象开发64:多态性

阿里云【名师课堂】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) {}
······
*/

在这里插入图片描述
通过程序,可以看出对象上转型的核心功能:操作参数统一。

总结

  1. 对象多态性实现的核心在于方法的覆写。
  2. 通过对象的上转型可以实现接收参数的统一,而向下转型可以实现子类扩充方法的调用(比较少用到);
  3. 两个没有关系的对象是不能进行转型的,所以下转型是存在安全隐患的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值