2.12 多态
2.12.1概述
某一个事物,在不同时刻表现出来的不同状态。
- 举例
猫可以是猫的类型。猫 m = new 猫();
同时猫也是动物的一种,也可以把猫称为动物
动物 d = new 猫();
- 多态的前提和体现
- 有继承关系
- 有方法重写
- 有父类引用指向子类对象
public class TestDemo {
public static void main(String[] args) {
//多态
Animal a = new Cat();
a.eat();
}
}
public class Cat extends Animal {
public int age = 20;
public int weight = 10;
public void eat() {
System.out.println("猫吃鱼");
}
public void playGame() {
System.out.println("猫捉迷藏");
}
}
public class Animal {
public int age = 40;
public void eat() {
System.out.println("吃东西");
}
}
2.12.2多态的优缺点:
优点:
提高了程序的扩展性
缺点:
不能访问子类特有功能
/*
* 多态的好处:提高了程序的扩展性
* 具体体现:定义方法的时候,使用父类型作为参数,将来在使用的时候,使用具体的子类型参与操作。
* 多态的弊端:不能使用子类的特有功能
*/
public class TestDemo {
public static void main(String[] args) {
AnimalOperator ao = new AnimalOperator();
Cat c = new Cat();
ao.useAnimal(c);
Dog d = new Dog();
ao.useAnimal(d);
Pig p = new Pig();
ao.useAnimal(p);
}
}
public class AnimalOperator {
/*
public void useAnimal(Cat c) { //Cat c = new Cat();
c.eat();
}
public void useAnimal(Dog d) { //Dog d = new Dog();
d.eat();
}
*/
public void useAnimal(Animal a) { //Animal a = new Cat();
a.eat();
}
}
public class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
}
public class Dog extends Animal {
public void eat() {
System.out.println("狗啃骨头");
}
public void lookDoor() {
System.out.println("狗看门");
}
}
public class Pig extends Animal {
public void eat() {
System.out.println("猪拱白菜");
}
}
2.12.3多态中的转型
体现:
- 父类的引用可以指向子类的对象
- 接口的引用可以指向实现类的对象
转型:
- 向上转型
由子类类型转型为父类类型,或者由实现类类型转型为接口类型
向上转型一定会成功,是一个隐式转换
向上转型后的对象,将只能访问父类或者接口中的成员
- 向下转型
由父类类型转型为子类类型,或者由接口类型转型为实现类类型
向下转型可能会失败,是一个显式转换(映射问题)
向下转型后的对象,将可以访问子类或者实现类中特有的成员
/*
* 向上转型
* 从子到父
* 父类引用指向子类对象
* 向下转型
* 从父到子
* 父类引用转为子类对象
*/
public class TestDemo {
public static void main(String[] args) {
//多态
Animal a = new Cat(); //向上转型
a.eat();
//a.playGame();
//多态的弊端:无法访问子类特有方法
//现在我就想使用子类特有方法,怎么办呢?
//创建子类对象就可以了
/*
Cat c = new Cat();
c.eat();
c.playGame();
*/
//现在的代码虽然可以访问子类的特有功能,但是不合理
//因为我们发现内存中有两个猫类的对象
//这个时候,我们得想办法把多态中的猫对象还原
//这个时候,就要使用多态中的转型了
//父类引用转为子类对象
Cat c = (Cat)a;
c.eat();
c.playGame();
}
}
public class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
public void playGame() {
System.out.println("猫捉迷藏");
}
}
public class Animal {
public void eat() {
System.out.println("吃东西");
}
}
2.12.4 instanceof关键字
针对于向下转型的。
如果向下转型不成功,会怎样?会有一个异常 ClassCastException
如何避免这种情况?在向下转型之前,我们先判断一下这个对象是不是要转型的类型怎么判断?
关键字 instanceof
Animal animal = new Dog();
if (animal instanceof Dog) {
// 说明animal的确是一个Dog
}
如果一个类中重写了父类的某一个方法。此时:
如果用这个类的对象来调用这个方法,最终执行的是子类的实现。
如果用向上转型后的对象来调用这个方法,执行的依然是子类的实现。
向上转型后的对象,归根到底还是子类对象。
public class TestDemo {
public static void main(String[] args) {
//多态
Animal a = new Cat(); //向下转型
Cat c = new Cat();
if(a instanceof Cat)
c = a
c.eat();
c.playGame();
}
}
public class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
public void playGame() {
System.out.println("猫捉迷藏");
}
}
public class Animal {
public void eat() {
System.out.println("吃东西");
}
}