目录
- 1.动态绑定机制
- 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正在管理!