面向对象多态性
面向对象的多态性体现在,一个对象有多种形态,例如:对象小明是一个学生,但也是一个人类。面向对象的多态性是建立在继承性之上的。
- 对象的向上转型。
对象的向上转型是安全的,创建子类当父类用。类和接口都是可以向上转型的。
父类 对象名 = new 子类();
接口 对象名 = new 实现类();
eg:
//父类
public class Fu {
int num = 10;
public void method1(){
System.out.println("父类方法执行");
}
public void method2(){
System.out.println(num);
}
public void methodFu(){
System.out.println("父类方法");
}
}
//子类
public class Zi extends Fu {
int num = 100;
int age = 20;
@Override
public void method1() {
System.out.println("子类方法执行");
}
@Override
public void method2() {
System.out.println(num);
}
public void methodZi(){
System.out.println("子类方法");
}
}
//main
public static void main(String[] args) {
Fu obj = new Zi();
obj.method1();//子类方法执行
System.out.println("========================");
//口诀:编译看左边,运行还看左边
// System.out.println(zi.age);//错误写法
System.out.println(obj.num);//100
obj.method2();//子类方法执行
System.out.println("=========================");
//口诀:编译看左边,运行看右边
//编译时方法必须是父类中有的方法
// 运行时会优先从子类中寻找,没有则向上找
obj.methodFu();//父类方法执行
// obj.methodZi();错误写法
}
这时用Fu obj = new Zi(); 语句创建的对象obj被当做父类来使用,obj只能运行子类重写的父类方法和父类中未被重写的方法。编译时能否通过要看obj.方法是否是父类定义中的方法,运行时却会先从子类重写方法中查找,没有则向上找。这样就会产生一个问题,子类中定义的自己的方法无法被调用,这时就需要对象向下转型。
2. 对象的向下转型。
当向上转型的对象,需要调用子类原本的方法时,就需要向下转型。向下转型不一定是安全的所以需要判断。
eg:
//父类
public abstract class Animal {
public abstract void eat();
}
//子类Cat
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void play(){
System.out.println("猫玩老鼠");
}
}
//子类Dog
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃shit");
}
public void watchHouse(){
System.out.println("狗看家");
}
}
//main
public class Demo01ClassCast {
public static void main(String[] args) {
//multi向上转型,一定是安全的。
Animal animal = new Cat();
animal.eat();//猫吃鱼
//但是会丧失cat类原本的方法play();
// animal.play();错误
//所以需要向下转型
Cat cat = (Cat) animal;
cat.eat();//猫吃鱼
cat.play();//猫玩老鼠
//向下转型如果不是还原回原本的类型
// 就会出现运行错误。
// Dog dog = (Dog) animal;//类转换错误,ClassCastException
System.out.println("===============================");
getPet(new Dog());//调用判断方法
}
public static void getPet(Animal animal){
//判断向下转型能否成功
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.eat();
dog.watchHouse();
}
if (animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.eat();
cat.play();
}
}
}
对于使用了Animal animal = new Cat();语句的animal来说,如果使用 Dog dog = (Dog) animal; 语句向下转型就会发生类转换错误( ClassCastException )。所以向下转型不一定是安全的,所以需要使用 instanceof关键字来判断。animal instanceof Cat为true值,证明可以向下转型。
- 多态的用处
如上例,我们只需要写一个方法getPet(Animal animal),就可以实现调用两个以上的子类方法。而传参只有一个animal,简化了方法数量,和方法参数。