多态(重点:成员方法编译看左边,访问看右边!!!)

先来说说“成员方法编译看左边,访问看右边”是什么意思。就是编译的时候看父类有没有这个方法,运行的时候是运行子类重写的方法。

什么是多态?

//形如此类为多态
Animal a = new Cat();

System.out.println(a.name);//输出的是Animal类(父类)中的成员变量name

System.out.println(a.eat());//输出的是Cat类(子类)中的重写方法eat()

多态存在的三个必要条件

一、要有继承;
二、要有重写;
三、父类引用指向子类对象。

多态的设计应用

传类参用多态父类,执行方法看子类重写
如:

//动物类Animal 猫类Cat 动物操作类AnimalOperator 测试类AnimalDemo

//动物类
public class Animal {
    public void eat() {
        System.out.println("动物吃东西");
    }
}

//猫类
public class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃老鼠");
    }
}

//动物操作类
public class AnimalOperator {
    public void useAnimal(Cat cat){
        cat.eat();
    }
}

//测试类
public class Test {
    public static void main(String[] args) {
        AnimalOperator animalOperator = new AnimalOperator();

        Cat cat = new Cat();
        animalOperator.useAnimal(cat);
    }
}

假设现在又多了一种动物类Dog,那么代码应该怎样改写?(动物类和猫类代码是不变的)

//狗类
public class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}

//动物操作类
public class AnimalOperator {
    public void useAnimal(Cat cat){
        cat.eat();
    }

    public void useAnimal(Dog dog){
        dog.eat();
    }
}

//测试类
public class Test {
    public static void main(String[] args) {
        AnimalOperator animalOperator = new AnimalOperator();

        Cat cat = new Cat();
        animalOperator.useAnimal(cat);
        
        Dog dog = new Dog();
        animalOperator.useAnimal(dog);
    }
}

重点来了!!!我们对比一下前后动物操作类的变化可以发现每增加一个新的具体动物的类,就得将动物操作类的方法重载一次,多了一次代码冗余。那么有没有什么办法可以使得无论再加多少种动物,动物操作类的代码都不变呢?Of Course!

//动物操作类
public class AnimalOperator {

    public void useAnimal(Animal animal) {

//        Animal animal1 = new Cat();
//        Animal animal1 = new Dog();
//这里就用到了多态的特点:编译看左边,访问看右边!!!
          animal.eat();
    }
}

//测试类
public class Test {
    public static void main(String[] args) {
        AnimalOperator animalOperator = new AnimalOperator();

        Animal cat = new Cat();
        animalOperator.useAnimal(cat);

        Animal dog = new Dog();
        animalOperator.useAnimal(dog);
    }
}

那这么做的好处是什么呢?比如此时多了一个类Pig,要输出Pig类的方法就无需改动AnimalOperater类的方法useAnimal(Animal a)的参数了(父类同为Animal),只需在测试类里将Pig类的引用作为参数传入即可。

弊端即只能访问重写的方法,子类独有的不能访问。那想访问子类独有的方法咋办呢???当然是用子类引用或者向下转型啦!

下课!

posted @ 2021-12-23 19:32  郑国荣  阅读(276)  评论(0编辑  收藏  举报