一、多态的概述
左边的是父类的引用,右边是子类的对象
代码举例说明什么是多态:
Animal类:
public class Animal {
public void eat() {
System.out.println("动物吃东西");
}
}
Cat类:
public class Cat extends Animal{
@Override
public void eat(){
System.out.println("猫吃鱼");
}
}
AnimalDemo类:
public class AnimalDemo {
public static void main(String[] args) {
Animal a=new Cat();
}
}
左边的是父类的引用,右边是子类的对象
二、多态中成员访问特点
代码演示访问成员变量:
Animal类:
public class Animal {
public int age = 40;
public void eat() {
System.out.println("动物吃东西");
}
}
Cat类:
public class Cat extends Animal{
public int age=20;
public int weight=10;
@Override
public void eat(){
System.out.println("猫吃鱼");
}
public void playGame(){
System.out.println("猫捉迷藏");
}
}
测试类:
我们以Animal引用类型创建了Cat对象,我们可以看到age可以访问到,但是weight访问不到,这是因为我们创建的a是Animal类型的引用类型,Animal中只有age,没有weight,所以访问不了
输出:
40
输出的是父类的age的值
总结:通过多态的形式访问成员变量访问的是父类中的,他的编译要看左边,运行也要看左边
代码演示访问成员方法:
发现palyGame无法访问
也就是说访问成员方法编译也要看左边,左边没有就不行
输出:
猫吃鱼
也就是说运行看的是子类的方法
总结:
他的编译要看左边,运行要看右边
三、多态的好处和弊端
1.好处
我们将不用多态的代码和使用多态的代码进行比较
不使用多态的代码
Animal类:
public class Animal {
public void eat() {
System.out.println("动物吃东西");
}
}
Cat类:
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
Dog类:
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
AnimalOperator类:
public class AnimalOperator {
public void useAnimal(Cat c){
c.eat();
}
public void useAnimal(Dog d){
d.eat();
}
}
测试类:
public class AnimalDemo {
public static void main(String[] args) {
//创建动物操作类的对象,调用方法
AnimalOperator animalOperator = new AnimalOperator();
Cat c = new Cat();
animalOperator.useAnimal(c);
Dog d=new Dog();
animalOperator.useAnimal(d);
}
}
输出:
猫吃鱼
狗吃骨头
我们可以发现,我们每添加一种动物,都需要在AnimalOperator类中增加其对应的方法,假如添加的动物非常多的话,就会非常的繁琐
使用多态的代码
只改变AnimalOperator类中的代码
public class AnimalOperator {
public void useAnimal(Animal animal){
animal.eat();
}
}
调用方法时将Cat传入
相当于是Animal animal=new Cat();
多态访问成员方法编译看左边,运行看右边
输出:
猫吃鱼
狗吃骨头
这样就不用每次都在AnimalOperator类中添加方法
2.弊端
当我们在子类再添加一个方法,这个方法不是重写父类的方法
Dog类:
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃骨头");
}
public void dogleg(){
System.out.println("狗腿子");
}
}
在AnimalOperator类中无法访问
也就是说多态的形式不能访问子类特有的功能
3.总结
四、多态的转型
因为我们说多态的形式不能访问子类特有的功能,所以需要用多态的转型来实现访问子类特有功能
父类引用指向子类对象就是向上转型
向下转型就是把父类引用转为子类对象,直接强转
五、多态转型的内存图解
首先执行main方法,main方法进栈,引用类型a指向new的地址001
a.eat执行猫里边的eat方法,执行完就出栈
执行:
引用变量a指向的就是001,是Cat类
是等价的,所以可以强转
执行a=new Dog();
此时a就指向了new的002地址,是一个dog类
执行强转
这个时候a指向的是002,是一个狗类,而Cat cc 是猫类,不能转换