天天看点

面向对象多态性

面向对象多态性

面向对象的多态性体现在,一个对象有多种形态,例如:对象小明是一个学生,但也是一个人类。面向对象的多态性是建立在继承性之上的。

  1. 对象的向上转型。

    对象的向上转型是安全的,创建子类当父类用。类和接口都是可以向上转型的。

    父类 对象名 = 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值,证明可以向下转型。

  1. 多态的用处

    如上例,我们只需要写一个方法getPet(Animal animal),就可以实现调用两个以上的子类方法。而传参只有一个animal,简化了方法数量,和方法参数。

继续阅读