目录
  • 1.动态绑定机制
    • 实例A
    • 实例B
    • 实例C
  • 2.多态数组
    • 3.多态数组的高阶用法
      • 4.多态参数
        • 5.多态参数的高阶用法

          1.动态绑定机制

          java的动态绑定机制非常重要

          实例A

          我们来看一个实例:

          深入解析Java多态进阶学习

          阅读上面的代码,请说明下面的程序将输出什么结果:

          深入解析Java多态进阶学习

          程序将会输出40和30,这个实例很简单,直接看运行类型即可,该代码的运行类型为B,所以会调用B类的方法

          实例B

          我们将上面的代码变通一下,将子类中的如下代码块注销:

          深入解析Java多态进阶学习

          随后继承机制会访问父类的sum方法:

          深入解析Java多态进阶学习

          那么这里有一个问题,此处的getI(),会执行子类的还是父类的呢?

          当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定

          代码的运行类型依然是B,所以此处会执行子类的getI()方法,结果输出为30

          实例C

          现在我们再变通以下上面的代码

          再将子类中如下的代码块注销:

          深入解析Java多态进阶学习

          继承机制会执行父类的sum1方法:

          深入解析Java多态进阶学习

          那么这里有一个问题,此处的i,会使用子类的还是父类的呢?

          属性没有动态绑定机制,哪里声明,哪里使用(使用当前类的)

          此处的i在父类进行声明,所以会选用父类的i属性,结果为20

          2.多态数组

          定义:

          数组的定义类型为父类类型,但是保存的实际元素类型为子类类型

          Person父类:

          /**
           * 多态数组父类
           */
          public class Person {
              private String name;
              private int age;
          
              public Person(String name, int age) {
                  this.name = name;
                  this.age = age;
              }
          
              public String getName() {
                  return name;
              }
          
              public void setName(String name) {
                  this.name = name;
              }
          
              public int getAge() {
                  return age;
              }
          
              public void setAge(int age) {
                  this.age = age;
              }
          
              public String say() {
                  return name + '\t' + age;
              }
          }
          

          Student子类:

          /**
           * 多态数组学生子类
           */
          public class Student extends Person{
              private double score;
          
              public Student(String name, int age, double score) {
                  super(name, age);
                  this.score = score;
              }
          
              // 重写父类的say方法
              public String say() {
                  return super.say() + '\t' + score;
              }
          }
          

          Teacher子类:

          /**
           * 多态数组教师子类
           */
          public class Teacher extends Person {
              private double sal;
          
              public Teacher(String name, int age, double sal) {
                  super(name, age);
                  this.sal = sal;
              }
          
              public double getSal() {
                  return sal;
              }
          
              public void setSal(double sal) {
                  this.sal = sal;
              }
          
              public String say() {
                  return super.say() + '\t' + sal;
              }
          }
          

          测试多态数组的使用:

          public class Test {
              public static void main(String[] args) {
                  // 多态数组的使用
                  Person[] persons = new Person[5];
                  persons[0] = new Person("dahe",20);
                  persons[1] = new Student("wangwei",11,100);
                  persons[2] = new Student("zhangsan",12,60);
                  persons[3] = new Teacher("wang",33,15000);
                  persons[4] = new Teacher("li",55,25000);
          
                  // 循环遍历多态数组,调用say方法
                  for (int i = 0; i < persons.length; i++) {
                      String out = persons[i].say(); // 动态绑定机制,编译类型永远都是Person
                      // 运行类型是根据实际情况由JVM机决定
                      System.out.println(out);
                  }
              }
          }
          
          

          输出:

          dahe    20
          wangwei    11    100.0
          zhangsan    12    60.0
          wang    33    15000.0
          li    55    25000.0

          3.多态数组的高阶用法

          现在,教师子类新增了教学方法:

          public void teach() {
              System.out.println("老师:" + getName() + "正在讲课!");
          }
          

          学生子类新增了学习方法:

          public void study() {
              System.out.println("学生:" + getName() + "正在学习!");
          }
          

          那么,有没有办法通过多态数组来访问他们子类对应的独有的方法呢?事实上,可以通过巧妙使用instanceof来解决:

          变通一下,改变多态数组的循环操作:

          // 循环遍历多态数组,调用say方法
          for (int i = 0; i < persons.length; i++) {
              String out = persons[i].say(); // 动态绑定机制,编译类型永远都是Person
              // 运行类型是根据实际情况由JVM机决定
              System.out.println(out);
              if (persons[i] instanceof Student) {
                  // 向下转型
                  Student student = (Student) persons[i];
                  student.study();
              } else if (persons[i] instanceof Teacher) {
                  Teacher teacher = (Teacher) persons[i];
                  teacher.teach();
              }
          }
          

          输出:

          dahe    20
          wangwei    11    100.0
          学生:wangwei正在学习!
          zhangsan    12    60.0
          学生:zhangsan正在学习!
          wang    33    15000.0
          老师:wang正在讲课!
          li    55    25000.0
          老师:li正在讲课!

          大功告成!多态数组即强大又完美!

          4.多态参数

          方法定义的形参类型为父类类型,实参类型允许为子类类型

          接下来我们来演示以下多态参数的使用:

          父类:

          /**
           * 多态参数 - 父类
           */
          public class Employee {
              private String name;
              private double sal;
          
              public Employee(String name, double sal) {
                  this.name = name;
                  this.sal = sal;
              }
          
              public String getName() {
                  return name;
              }
          
              public void setName(String name) {
                  this.name = name;
              }
          
              public double getSal() {
                  return sal;
              }
          
              public void setSal(double sal) {
                  this.sal = sal;
              }
          
              // 得到年工资的方法
              public double getAnnual() {
                  return 12 * sal;
              }
          }
          

          员工子类:

          /**
           * 多态参数 - 子类员工
           */
          public class Worker extends Employee{
              public Worker(String name, double sal) {
                  super(name, sal);
              }
          
              public void work() {
                  System.out.println("普通员工:" + getName() + "正在工作!");
              }
          
              public double getAnnual() {
                  return super.getAnnual();
              }
          }
          

          经理子类:

          /**
           * 多态参数 - 经理子类
           */
          public class Manager extends Employee{
              private double bonus; // 奖金
          
              public Manager(String name, double sal, double bonus) {
                  super(name, sal);
                  this.bonus = bonus;
              }
          
              public double getBonus() {
                  return bonus;
              }
          
              public void setBonus(double bonus) {
                  this.bonus = bonus;
              }
          
              public void manage() {
                  System.out.println("经理:" + getName() + "正在管理!");
              }
          
              @Override
              public double getAnnual() {
                  return super.getAnnual() + bonus;
              }
          }
          

          我们来测试一下,求不同岗位的雇员的年薪:

          /**
           * 多态参数测试类
           */
          public class Test {
              public static void main(String[] args) {
                  Worker zhang = new Worker("张工",1000);
                  Manager milan = new Manager("milan", 5000, 2000);
                  Test test = new Test();
                  test.showEmpAnnual(zhang);
                  test.showEmpAnnual(milan);
              }
          
          
              // 获取员工的年薪,采用多态参数
              public void showEmpAnnual(Employee e) {
                  System.out.println(e.getAnnual());
              }
          }
          

          输出:

          12000.0
          62000.0

          5.多态参数的高阶用法

          我们来对上面的多态参数代码做一个完善,如果传入的是员工,则调用自己的work方法,如果传入的是经理,则调用自己的manage方法

          增加一个下面的方法:

          public void testWork(Employee e) {
              if (e instanceof Worker) {
                  ((Worker) e).work(); // 向下转型
              } else if (e instanceof Manager) {
                  ((Manager) e).manage();
              }
          }
          

          测试:

          test.testWork(zhang);
          test.testWork(milan);
          

          输出:

          普通员工:张工正在工作!
          经理:milan正在管理!

          声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。