属性没有多态一说
只能看编译类型(这里只是说main里的,其余的方法都是看调用的哪个类的用哪个类里的属性)
只有方法和对象有多态
多态方便
public void show(Cat a,Fish b);
public void show(Dog c,Bone d);
代码复用性差
让Cat和Dog为Animal子类
让Fish和Bone为Food子类
可以直接定义
public void show(Animal a,Food b);//因为对象的多态性,可以符合
1.方法的多态
方法的重载和重写都体现了多态
明明调用的相同方法名
却可以进行不同的操作(就叫多态)
2.对象的多态
编译看左边,运行看右边
重点
(1)
Animal animal=new Dog();//可以用父类的引用指向子类的对象
编译类型是Animal,运行类型是Do
(2)和(3)
在执行了(1)的代码后执行
animal=new Cat();
编译类型还是Aniaml但是运行类型从Dog变为Cat
来直接看代码吧,编译类型和运行类型造成的影响
最后输出的小狗,所以是执行的运行类型
3.多态的向上转型
本质:父类(一直到Object都算)的引用指向子类的对象
Animal a=new Dog();//Object obj = new Cat();
特点
编译类型看左边,运行类型看右边
可以调用父类的所有成员(遵守访问权限)
不能调用子类的特有成员
最终运行效果看子类的具体实现
多态中强调:编写java程序时,引用类型变量只能调用其编译时类型的变量,不能调用其运行时类型变量。
在程序运行之前是要先编译的,父类引用的类型是父类
虽然按照运行类型来讲子类中有这个方法
但是在编译时没有找到父类中的这个方法
因此就没有通过编译,更别说运行了
!!!!!!!!!!!!!!
解释:
1.先编译,javac运行看左边的,只有左边的会加载出来
2.然后运行,运行看右边的,把右边的再加载出来
然后从运行类开始找方法,就近原则
比如你调用
Sleep()方法,先从Cat的类里面找
找不到再找它的父类,所以运行的是右边的方法(子类的方法)
也就叫运行看右边,右边没有再看父类直至Object
所以会有
Animal和Cat都有Sleep()方法
调用
a.Sleep();
调用的是Cat里的方法
但如果你就想通过这个变量调用子类的特有方法怎么办
有办法,那就是再次向下转型
4.多态的向下转型
语法:子类类型 引用名 = (子类类型)父类引用;
举例
Animal animal=new Dog("大黄");
Dog a=(Dog) animal;
注意:
1.建立在向上转型的基础上
2.只可强转父类的引用,而不是父类的对象
3.要求父类引用指向的对象和强转的类型相同(或者是它的父类,但重写方法一般不会孙子重写爷爷的方法,所以可以这么理解)
4.作用:可以调用子类的所有成员,执行后相当于Dog animal=new Dog();
这是我对于3里的小括号,给出来的图片,可以发现,没有报错,所以是可行的
也是可以正常运行的