深入解析Java多态进阶学习

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

1.动态绑定机制

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

实例A

我们来看一个实例:

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

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

实例B

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

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

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

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

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

实例C

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

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

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

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

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

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

2.多态数组

定义:

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

Person父类:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

/**

 * 多态数组父类

 */

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子类:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

/**

 * 多态数组学生子类

 */

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子类:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

/**

 * 多态数组教师子类

 */

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;

    }

}

测试多态数组的使用:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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.多态数组的高阶用法

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

?

1

2

3

public void teach() {

    System.out.println("老师:" + getName() + "正在讲课!");

}

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

?

1

2

3

public void study() {

    System.out.println("学生:" + getName() + "正在学习!");

}

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

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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

// 循环遍历多态数组,调用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.多态参数

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

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

父类:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

/**

 * 多态参数 - 父类

 */

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;

    }

}

员工子类:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

/**

 * 多态参数 - 子类员工

 */

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();

    }

}

经理子类:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

/**

 * 多态参数 - 经理子类

 */

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;

    }

}

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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

/**

 * 多态参数测试类

 */

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方法

增加一个下面的方法:

?

1

2

3

4

5

6

7

public void testWork(Employee e) {

    if (e instanceof Worker) {

        ((Worker) e).work(); // 向下转型

    } else if (e instanceof Manager) {

        ((Manager) e).manage();

    }

}

测试:

?

1

2

test.testWork(zhang);

test.testWork(milan);

输出:

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

猜你喜欢

转载自blog.csdn.net/qq_15509251/article/details/131549506
今日推荐