目录
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正在管理!