Java多态

多态概述

多态是面向对象三大特征之一,是同一个对象,在不同时刻表现出来的不同形态的能力。

二哈

举个例子:二哈;
我们可以说二哈是狗:Dog erha = new Dog();
我们也可以说二哈是动物:Animal erha = new Animal();
同样这只二哈,在不同的时刻表现出来了不同的形态,这就是多态。

多态的三个必要条件:

  • 继承
  • 子类重写父类方法
  • 有父类引用指向子类对象

怎么理解这三个条件呢,直接上代码:

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

// 狗狗类(继承了动物类)
class Dog extends Animal {
    // 重写父类eat()方法
    @Override
    public void eat() {
        System.out.println("狗狗吃骨头");
    }
}

// Demo类
public class PolymorphismDemo {
    public static void main(String[] args) {
        // 父类引用指向子类对象
        Animal erha = new Dog();
        erha.eat();
    }
}

最后的运行结果是狗狗吃骨头,三个条件我在注释中也都标注了出来。这就是最基本的一个多态案例。

多态中成员访问特点

  • 成员变量:编译看左边,执行看左边
Animal erha = new Dog();
System.out.println(erha.name); // erha.name只能取到父类Animal中的值
  • 成员方法:编译看左边,执行看右边
Animal erha = new Dog();
erha.eat(); // erha.eat()调用的是子类Dog重写后的方法

怎么理解这两句话呢,直接上代码:

// 动物类
class Animal {
    public String name = "动物";

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

// 狗狗类
class Dog extends Animal {
    public String name = "狗狗";

    @Override
    public void eat() {
        System.out.println("狗狗吃骨头");
    }
}

// Demo类
public class PolymorphismDemo2 {
    public static void main(String[] args) {
        Animal erha = new Dog();
        System.out.println(erha.name);
        erha.eat();
    }
}

最后的运行结果是:

动物
狗狗吃骨头

为什么成员变量和成员方法的访问不一样呢?
因为成员方法有重写,eat()被子类重写了;而成员变量没有重写,访问的依然是父类的name

多态的弊端

不能使用子类的特有功能,举个例子

// 动物类
class Animal {
    public String name = "动物";

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

// 狗狗类
class Dog extends Animal {
    public String name = "狗狗";
    public int age = 5;

    @Override
    public void eat() {
        System.out.println("狗狗吃骨头");
    }

    public void bark(){
        System.out.println("狗狗汪汪叫");
    }
}

// Demo类
public class PolymorphismDemo3 {
    public static void main(String[] args) {
        Animal erha = new Dog();
        System.out.println(erha.name);
        erha.eat();

        //System.out.println(erha.age); //ERROR
        //erha.bark(); //ERROR
    }
}

因为这个erha是父类引用(Animal)指向子类对象(Dog)所创建出来的,子类的特有功能agebark()这边都没法获取,所以这边两行都会报错。

多态中的转型

  • 向上转型:父类引用指向子类对象
  • 向下转型:父类引用转为子类对象
Animal a = new Dog(); // 向上转型,父类引用指向子类对象
Dog d = (Dog) a; // 向下转型,父类引用被强制转换为子类对象

在代码中实现:

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

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

    public void bark(){
        System.out.println("狗狗汪汪叫");
    }
}

// Demo类
public class PolymorphismDemo4 {
    public static void main(String[] args) {
        Animal erha = new Dog(); // 向上转型
        erha.eat();
        //erha.bark(); //ERROR

        Dog xiaoha = (Dog) erha; // 向下转型
        xiaoha.eat();
        xiaoha.bark();
    }
}

最后的运行结果是:

狗狗吃骨头
狗狗吃骨头
狗狗汪汪叫

在向上转型中,由于是父类引用指向子类对象,因此无法调用bark()方法,而在向下转型中,父类引用转为子类对象,因此可以调用子类的bark()方法。

原文地址:https://www.cnblogs.com/Subaru/p/15741404.html