Java基础 第二节 第十五课
概述
引入
多态是继封装, 继承之后, 面向对象的第三大特征.
生活中, 比如跑的动作, 小猫, 小狗和大象, 跑起来是不一样的. 在比如飞的动作, 昆虫, 鸟类和飞机, 飞起来也是不一样的. 可见, 同一行为, 通过不同的事物, 可以体现出来的不同的形态. 多态, 描述的就是这样的状态.
定义
多态: 是指同一行为, 具有多个不同的表现形式.
前提
- 继承或者实现 (二选一)
- 方法的重写 (意义体现: 不重写, 无意义)
- 父类引用指向子类对象 (格式体现)
多态的体现
多态体现的格式:
父类类型 变量名 = new 子类对象;
变量名.方法名();
- 1
- 2
注: 父类类型: 指子类对象继承的父类类型, 或者实现的父类接口类型.
代码如下
Fu f = new Zi();
f.method();
- 1
- 2
当使用多态方式调用方法时, 首先检查父类中是否有该方法. 如果没有, 则编译错误; 如果有则执行的是子类重写后的方法.
代码展示
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("吃鱼");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("吃狗粮");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
定义测试类:
public class Test2 {
public static void main(String[] args) {
// 多态形式, 创建对象
Animal animal1 = new Cat();
// 调用的是Cat的eat
animal1.eat(); // 调试输出: 吃鱼
// 多态形式, 创建对象
Animal animal2 = new Dog();
// 调用的是Dog的eat
animal2.eat(); // 调试输出: 吃狗粮
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
多态的好处
实际开发的过程, 父亲类型作为方法形式参数, 传递子类对象给方法, 进行方法符调用. 这样更能体现出多态的扩展性与便利.
代码如下:
public class Test3 {
public static void main(String[] args) {
// 多态形式,创建对象
Cat c = new Cat();
Dog d = new Dog();
// 调用showCatEat
showCatEat(c);
// 调用showDogEat
showDogEat(d);
/*
以上两个方法, 均可以被showAnimalEat(Animal a)方法所替代
而执行效果一致
*/
showAnimalEat(c);
showAnimalEat(d);
}
public static void showCatEat (Cat c){
c.eat();
}
public static void showDogEat (Dog d){
d.eat();
}
public static void showAnimalEat (Animal a) {
a.eat();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 由于多态的特性的支持, showAnimalEat 方法的 Animal 类型, 是 Cat 和 Dog 的父类类型. 父类类型接收子类对象, 当然可以把 Cat 对象和 Dog 对象, 传递给方法
- 当 eat 方法执行时, 多态规定, 执行的是子类重写的方法. 那么效果自然与 showCatEat, showDogEat 方法一致. 所以, showAnimalEat 完全可以替代以上两种方法
- 不仅仅是替代, 在扩展性方面, 无论之后再多的子类出现, 我们都不需要编写 showXxxEat 方法了. 直接使用 showAnimalEat 都可以完成
所以, 多态的好处体现在: 可以使程序编写的更简单, 并有良好的扩展性.
引用类型转换
多态的转型分为向上转型与向下转型两种.
向上转型
向上转型: 多态本身是子类类型向父类类型向上转换的过程, 这个过程是默认的. 即, 当父类引用指向一个子类对象是, 便是向上转型.
使用格式:
父类类型 变量名 = new 子类类型();
如:Animal a = new Cat();
- 1
- 2
向下转型
向下转型: 父亲类型向子类类型向下转换的过程, 这个过程是强制的. 即, 一个已经向上转型的子类地下, 将父类引用转为子类引用. 可以使用强制类型转换格式, 便是向下转型.
使用格式:
子类类型 变量名 = (子类类型) 父类变量名;
如:Cat c =(Cat) a;
- 1
- 2
为什么要转型
当使用多态方式调用方法时, 首先检测父类中是否有该方法. 如果没有, 则编译错误. 也就是说, 不能调用子类拥有而父类没有的方法. 编译都错误, 更别谈运行了. 这也是多态给我们带来的一点 “小麻烦”. 所以, 想要调用子类特有的方法, 必须做向下转型.
转型演示, 代码如下:
定义类
public abstract class Animal {
abstract void eat();
}
class Cat extends Animal{
@Override
void eat() {
System.out.println("吃鱼");
}
public void catchMouse() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃狗粮");
}
public void watchHouse() {
System.out.println("看家");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
定义测试类
public class Test {
public static void main(String[] args) {
// 向上转型
Animal animal = new Cat();
animal.eat(); // 调用的是Cat的eat
// 向下转型
Cat cat = (Cat)animal;
cat.catchMouse(); // 调用的是Cat的catchMouse
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
执行结果:
转型的异常
转型的过程中, 一不小心就会遇到这样的问题, 请看如下代码:
public class Test {
public static void main(String[] args) {
// 向上转型
Animal animal = new Cat();
animal.eat(); // 调用的是Cat的eat
// 向下转型
Dog dog = (Dog)animal;
dog.watchHouse(); // 调用的是Dog的watchHouse (报错)
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
执行结果:
这段代码可以通过编译, 但是运行时, 却报出了ClassCaseException
, 类型转换异常. 这是因为, 明明创建了 Cat 类型对象, 运行时, 当然不能转换成 Dog 对象的. 这两个类型并没有任何继承关系, 不符合类型转换的定义.
为了避免```ClassCastException``的发生, Java 提供了 instanceof 关键字, 给引用变量做类型的校验, 格式如下:
变量名 instanceof 数据类型
如果变量属于该数据类型, 返回true
如果变量不属于该数据类型, 返回false
- 1
- 2
- 3
所以, 转换前, 嗯最好先做一个判断. 代码如下:
public class Test3 {
public static void main(String[] args) {
// 向上转型
Animal animal = new Cat();
animal.eat(); // 调用的是Cat的eat
// 向下转型
if (animal instanceof Cat){
Cat cat = (Cat)animal;
cat.catchMouse(); // 调用的是 Cat的catchMouse
} else if (animal instanceof Dog){
Dog d = (Dog)animal;
d.watchHouse(); // 调用的是 Dog的watchHouse
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
文章来源: iamarookie.blog.csdn.net,作者:我是小白呀,版权归原作者所有,如需转载,请联系作者。
原文链接:iamarookie.blog.csdn.net/article/details/110156536
- 点赞
- 收藏
- 关注作者
评论(0)