多态(polymorphism):事物在运行过程中存在不同的状态

多态的存在有三个前提:

  1. 要有继承或实现关系
  2. 子类要重写父类的方法
  3. 父类引用指向子类对: Fu fu = new Zi()

下面我们举一个老板和员工的例子:
首先定义一个父类:Employee员工类
再定义两个子类:Teacher老师类和Assistant助教类

public class Employee {
    String name = "BOSS";
    int age = 18;

    public static void getCompanyName() {
        System.out.println("Apple");
    }

    public void work() {
        System.out.println("进行工作");
    }

}
public class Teacher extends Employee{
    String name = "Teacher";
    int age = 200;

    @Override
    public void work(){
        System.out.println("上课");
    }

    //注意这里不叫Override,叫掩盖父类的方法,相当于重新写了私有成员方法
    public static void getCompanyName(){
        System.out.println("ccc");
    }

    public void teachAssistant(){
        System.out.println("institute AS");
    }
}
public class Assistant extends Employee{
    String name = "Assistant";
    int age = 100;

    @Override
    public void work(){
        System.out.println("改作业");
    }

    public static void getCompanyName(){
        System.out.println("bbb");
    }

    public void listenTeacher(){
        System.out.println("Learning");
    }
}
public class Main {
    public static void main(String[] args) {
        Employee emp1 = new Teacher();
        System.out.println(emp1.name+" "+emp1.age);//成员变量看左边:BOSS 18
        emp1.work();//成员方法看右边:上课
        Teacher.getCompanyName();//子类的静态成员方法,跟对象不相关
        emp1.getCompanyName();//静态方法,因为多态不能访问专属子类的成员方法,要去父类找
        //emp1.teachAssitant();//不能调用子类专属方法
        System.out.println("================");

        Employee emp2 = new Assistant();
        System.out.println(emp2.name+" "+emp2.age);//成员变量看左边:BOSS 18
        emp2.work();//成员方法看右边:改作业
        Assistant.getCompanyName();
        emp2.getCompanyName();

    }
}
BOSS 18
上课
ccc
Apple
================
BOSS 18
改作业
bbb
Apple
  • 从上面的例子可以看到我们重写了work方法,因为不同的员工有不同的方法。Teacher是上课Assistant是改作业,用多态的时候创建的时候,名义上创建的是一个Employee,但是当他们去work的时候,干的却是不同的活。可以用老板和员工来解释,大老板没必要知道员工是啥岗位,只要知道这些员工能工作就好,具体干什么工作,不用去管他们。发送work()指令,就能让他们自己干自己的活去了

在多态中成员函数的特点

在编译时期:参阅引用型变量所属的类是否有调用方法。如果有,编译通过,如果没有编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。

在多态中,成员变量的特点:
无论编译和运行,都参考左边(引用型变量所属的类)。

理解
Employee emp1 = new Teacher()语句在堆内存中开辟了子类Teacher的对象,并把栈内存中的父类Employee的引用指向了这个Teacher对象。