03_面向对象高级_多态
多态
1. 什么是多态?
“多态” 是在 “继承” 的基础上实现的一种现象,具体表现为:对象多态、行为多态。
public class HelloWorld {
public static void main(String[] args) {
// 1. 对象多态
Human h1 = new Student();
Human h2 = new Teacher();
// 2. 行为多态
h1.run(); // 学生跑得贼快~~
h2.run(); // 老师跑得贼快~~
}
}
class Human {
public void run() {
System.out.println("人会跑步~~");
}
}
class Student extends Human {
public void run() {
System.out.println("学生跑得贼快~~");
}
}
class Teacher extends Human {
public void run() {
System.out.println("老师跑得贼快~~");
}
}
2. 注意事项
多态是对象或行为的多态,Java中的属性 (成员变量) 不谈多态。
public class HelloWorld {
public static void main(String[] args) {
// 1. 对象多态
Human h1 = new Student();
Human h2 = new Teacher();
// 2. 属性(成员变量)是没有多态的
System.out.println(h1.name); // "父类 Human"
System.out.println(h2.name); // "父类 Human"
}
}
class Human {
public String name = "父类 Human";
}
class Student extends Human {
public String name = "子类 Student";
}
class Teacher extends Human {
public String name = "子类 Teacher";
}
3. 多态的好处
3.1 在多态形式下,可以实现解耦合,右边对象可以随时切换,后续业务随机改变
// 当 Student() 不好用时,完全可以不改变下面的h1.run()...等代码,直接换成 Teacher() 即可
Human h1 = new Student();
h1.run();
h1.get();
h1.xxx......
......
3.2 定义方法时,使用父类类型的形参,可以接收一切子类对象,扩展性更强,更便利
public class HelloWorld {
// main方法,程序入口
public static void main(String[] args) {
Human h1 = new Student();
Human h2 = new Teacher();
// 可以使用父类类型的变量作为形参,可以接收一切子类对象,方便到时候修改
goToSchool(h1);
goToSchool(h2);
}
// 自定义方法
public static void goToSchool(Human h) {
System.out.println(h + "去学校了");
}
}
class Human {
}
class Student extends Human {
}
class Teacher extends Human {
}
4. 多态的类型转换
种类:
- 自动类型转换 —— 例如
Human h = new Teacher()
- 强制类型转换 —— 例如
Teacher t = (Teacher) h
作用:通过把对象转换成真正的类型,从而解决了多态下不能调用子类独有方法的问题。
注意:
- 存在继承时,就可以强制类型转换,编译阶段不会报错;
- 但是在运行阶段,如果发现对象的真实类型与强制转换后的类型不同,就会报错!( ClassCastException )
- 因此,强制类型转换前,使用 instanceof 判断当前对象的真实类型。
public class HelloWorld {
public static void main(String[] args) {
// 1. 对象多态
Human h1 = new Student();
Human h2 = new Teacher();
// 2. 行为多态
h1.run(); // 学生跑得贼快~~
h2.run(); // 老师跑得贼快~~
// 3. 对象无法使用自己的独有功能
// h1.test() // 报错
// h2.teach() // 报错
// 4. 想要使用独有的功能,就必须强制类型转换
Student s = (Student) h1;
Teacher t = (Teacher) h2;
s.test(); // 学生需要考试
t.teach(); // 老师需要教学
// 5. 如果你不确定 h1 是什么类型的,强制类型转换在编译时没问题,但是运行时可能会报错
// Teacher tt = (Teacher) h1; // 运行报错,因为 h1 本质是Student类的对象,不可能转为Teacher类的对象
// 6. 解决上面的问题
judge(h1); // 学生需要考试
}
// 自定义方法
public static void judge(Human h) {
// 6. 为了解决上面的问题方案,需要利用instanceof做个判断(类型一致返回true,否则返回false)
if (h instanceof Teacher) {
Teacher t = (Teacher) h;
t.teach();
} else if (h instanceof Student) {
Student s = (Student) h;
s.test();
}
}
}
class Human {
public void run() {
System.out.println("人会跑步~~");
}
}
class Student extends Human {
public void run() {
System.out.println("学生跑得贼快~~");
}
// 学生独有功能
public void test() {
System.out.println("学生需要考试");
}
}
class Teacher extends Human {
public void run() {
System.out.println("老师跑得贼快~~");
}
// 老师独有功能
public void teach() {
System.out.println("老师需要教学");
}
}