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("老师需要教学");}
}