文章目录
前言(转载请说明作者!)4.8编写
在学习日志Ⅵ(继承)中,我们使用学生类和教师类来继承人类,从而有效解决了一些代码冗余的问题,实现了代码的复用。
而在多态中,我们还有更加简便的方式来解决同一种方法,参数属于同一父类的方法,使得程序更加简洁。
多态
学校门禁系统实现
导引
我们在继承中编写了程序,现根据它来增加一个学校类(Shool),学校类中有门禁系统,可以为学生和老师开门。
代码(非多态实现)
Person类
public class Person {
private String name;
private int age;
// 有参构造方法
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public void printInfo() {
System.out.println("姓名:" + name + "\n年龄:" + age);
}
// getter/setter
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;
}
}
Student类
public class Student extends Person {
private String department;
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public Student(String name, int age, String department) {
super(name, age);
this.department = department;
}
public void printInfo() {
super.printInfo();
System.out.println("系别:"+department);
}
}
Teacher类
public class Teacher extends Person {
private String major;
public String getMajor() {
return major;
}
public void setMajor(String major) {
this.major = major;
}
public Teacher(String name, int age, String major) {
super(name, age);
this.major = major;
}
public void printInfo() {
super.printInfo();
System.out.println("专长:" + major);
}
}
School类(非多态)
public class School {
// 为学生开启门禁
public void openDoor(Student stu) {
stu.printInfo();
System.out.println("允许进入!");
}
// 为老师开启门禁
public void openDoor(Teacher t) {
t.printInfo();
System.out.println("允许进入!");
}
}
主类(EX8_1)
public class EX8_1 {
public static void main(String[] args) {
School sc = new School();
Student stu = new Student("小明", 20, "音乐学院");
sc.openDoor(stu);
System.out.println("*****************************");
Teacher t = new Teacher("刘老师", 30, "信息工程");
sc.openDoor(t);
}
}
输出:
姓名:小明
年龄:20
系别:音乐学院
允许进入!
姓名:刘老师
年龄:30
专长:信息工程
允许进入!
本章会改进此案例,把它加入多态的特性。
什么是多态?
多态,顾名思义,字面意义是“多种状态”,就是指 不同的对象调用相同的方法执行的操作不同 。
后面我们会学习接口相关的知识,也可以说同一实现接口,使用不同的实例可以执行不同的操作。
在学校类的开启 门禁就是学校提供的一个接口,这个接口应该可以为不同类型的人开启门禁 ,比如可以为学生,教师,管理员等开启门禁,这就是一种多态。
如何实现多态?
对象的上转型对象
上转型类型类似基本数据类型的转换。
e.g.1 整形可以转换为双精度浮点型
int n = 23; double m = n; 最终m的值为23.0。
e.g.2 双精度型转换为整形需要强制类型转换
int n = (int)8.2; 最终n的值为8。
定义
在引用数据类型的子类和父类之间也存在转换问题,子类对象可以赋给父类对象(不需要强制类型转换) ,叫做子类对象向上转型 。父类对象称为子类对象的 上转型对象 。
Person p;
Student stu = new Student();
p = stu; // 称作stu向上转型
上述的 p = stu 中的 p称作 stu的上转型对象。
上述的代码还可以简写成:
Person p = new Student();
p就称为 new Student()对象的上转型对象 。
特点
上转型对象的类型是父类类型 ,实体 却是 由子类 负责 创建 的。
- 上转型对象 会失去子类对象的一些属性和方法 。上转型对象不能操作子类新增的成员变量(即丢失了这部分属性),不能使用子类新增的方法(即丢失了这部分方法)。
- 上转型对象 可以操作子类继承或者隐藏成员变量 ,也 可以使用子类继承的或者重写的方法 。
- 上转型对象操作子类继承或者重写的方法时,就是通知对应的子类对象来调用这些方法。所以, 如果子类重写了父类的某个方法,对象的上转型对象调用这个方法时,一定是调用了重写后的方法 。
- 可以将对象的上转型对象再强制转换到一个子类对象 ,这时,该子类又会具备子类所具有的属性和功能 。
上转型对象的案例
主类(EX8_2)
PS:其他类同非多态实现的门禁系统
public class EX8_2 {
public static void main(String[] args) {
Person p;
Student stu = new Student("小红", 22, "外语系");
p = stu; // p是stu的上转型对象
// p不能调用新增的setDepartment方法
p.setName("小花");
p.printInfo();
Student stuNew = (Student) p;
stuNew.setDepartment("信工");
stuNew.printInfo();
}
}
输出:
姓名:小花
年龄:22
系别:外语系
姓名:小花
年龄:22
系别:信工
多态的实现
根据上述的了解,我们现在可以尝试制作程序来对门禁系统进行改进。
School类的修改
其他类均为进行修改,即可实现与之前完全相同的结果。
public class School {
// // 为学生开启门禁
// public void openDoor(Student stu) {
// stu.printInfo();
// System.out.println("允许进入!");
// }
//
// // 为老师开启门禁
// public void openDoor(Teacher t) {
// t.printInfo();
// System.out.println("允许进入!");
// }
// 多态的实现
public void openDoor(Person p) {
p.printInfo();
System.out.println("允许进入!");
}
}
温馨提示:
p.printInfo()方法调用的是子类重写后的方法 ,所以实现了多态 ,即不同参数传入相同的方法,结果却不相同。
如果我们再创建一个管理员类,并且是Person的子类,那么门禁系统不需要进行修改即可对管理员进行放行。有效避免了代码的重写。
多态实现的条件
多态实现有三个条件:继承、重写、向上转型。
继承
在多态中必须存在有继承关系的子类和父类 。如上述例子中:Student和Teacher都继承父类Person。
重写
子类对父类中某些方法进行重写,在调用这些方法时就会调用子类重写的方法 。如上述例子中:Student和Teacher都重写了父类Person中的printInfo()方法。
向上转型
在多态中需要将子类的引用赋给父类对象 ,编译时按照父类来处理,!!!!不能调用新增的成员!!!!! ,运行时绑定子类,调用子类重写方法 。如上述例子中:Student对象和Teacher对象向父类Person转型后调用相应重写后的printInfo()方法,输出不同,体现多态。
!!!!不能调用新增的成员!!!!
Instanceof运算符
这里的知识点较为简单,可以简述为:
实例 instanceof 类 == true;
instanceof就是判断前面的是否是后面的实例 。是就为true,不是就false。(即返回值类型为布尔型)
主要用途
可以用在多态方法中,用来分支运行不同子类的不同方法。