1.多态的形式
1.1 多态的基本概念
同一个类型,在不同的状态下会表现出不同的行为。
1.2 多态的形式
父类类名 对象名称 = new 子类构造器;
接口名称 对象名称 = new 实现类构造器;
父类的范围 > 子类的范围。
1.3 多态的识别技巧
- 对于方法的调用:编译看左边,运行看右边。
- 对于变量的访问:编译看左边,运行也看左边。
1.4 多态的的使用前提
- 必须有继承或者实现关系。
- 必须有父类类型的变量引用子类类型的对象。
- 需要存在方法重写。
1)代码示例
package cn.guardwhy_05;
// 基类:Animal
class Animal{
// 成员变量
public String name = "动物的总称";
// 成员方法
public void run(){
System.out.println("动物都能吃东西");
}
}
// 派生类:Cat
class Cat extends Animal{
public String name = "猫";
@Override
public void run() {
System.out.println("猫在屋子吃鱼..");
}
}
// 派生类:Dog
class Dog extends Animal{
public String name = "狗";
@Override
public void run() {
System.out.println("狗拿耗子,没有多管闲事..");
}
}
// 测试类:
public class PolymorphicDemo01 {
public static void main(String[] args) {
// 父类名称 对象名称 = new 子类构造器
Animal as1 = new Cat();
as1.run(); // 编译看左边,运行看右边 // 猫在屋子吃鱼..
System.out.println(as1.name); // 编译看左边,运行看左边 // 动物的总称
// 创建对象
Animal as2 = new Dog();
as2.run(); // 编译看左边,运行看右边
}
}
2)执行结果
2.多态的优劣
2.1 多态的优势
1)在多态的形势下,右边的对象可以实现组件化解耦思想。可以随时切换业务逻辑,而不需要更改过多代码,遍历系统的维护,拓展和管理。
2)实际开发的过程中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用。
这样该方法可以接收一切子类对象的类型。更能体现出多态的扩展性与便利。
2.2 多态的劣势
多态形式下无法调用子类独有的功能,因为编译看左边,左边没有子类独有的功能就直接报错!!
1)代码示例
package cn.guardwhy_05;
// 基类:Animal
class Animal1{
// 成员方法
public void run(){
System.out.println("动物都能吃东西");
}
}
// 派生类:Cat
class Cat1 extends Animal1{
@Override
public void run() {
System.out.println("猫在屋子里跑步..");
}
// 特有功能
public void eat(){
System.out.println("猫吃鱼...");
}
}
// 派生类:Dog
class Dog1 extends Animal1{
@Override
public void run() {
System.out.println("狗拿耗子,没有多管闲事..");
}
}
// 测试类
public class PolymorphicDemo02 {
public static void main(String[] args) {
// 创建对象
Animal1 as = new Cat1();
// 对象调用方法
as.run();
// a.catchMouse(); // 多态下无法调用子类独有的功能,编译看左边
Animal1 cs = new Cat1();
start(cs);
Animal1 ds = new Dog1();
start(ds);
}
// 开发一个动物大赛
public static void start(Animal1 a){
a.run();
}
}
2) 执行结果
3. 自动类型转换
3.1 自动类型转换前提
必须有继承关系才可以类型转换!!
3.2 引用类型的自动类型转换
子类对象或者子类类型的变量是可以直接自动类型转换给父类类型的变量(自动类型转换,向上转型)
1)代码示例
// 基类:Person
class Person{
}
// 派生类:Student
class Student extends Person{
}
// 测试类
public class PolymorphicDemo03 {
public static void main(String[] args) {
Person ps = new Student(); // 子类对象赋值给父类类型的变量,自动类型转换。
Student stu = new Student();
Person ps1 = stu; // 子类类型的变量赋值给父类类型的变量,自动类型转换。
}
}
4.强制类型转换
父类对象或者父类类型的变量赋值给子类类型的变量必须进行强制类型转换,否则报错!
4.1 强制类型转换的格式
子类名称 对象名称 = (子类名称)父类对象或者父类类型的变量。
4.2 类型转换异常
- 在编译阶段只要有继承关系的两个类型一定可以进行强制类型转换,编译阶段一定不会报错。
- 但是运行阶段可能出现:类型转换异常ClassCastException。类型转换异常:在运行阶段发现转型以后的类型根本不一致,就抛出错误。
4.3 instanceof关键字
- Java建议在进行类型转换之前先进行具体类型的判断,再强制类型转换:instanceof使用格式: 变量 instanceof 类型
- 判断变量的真实类型是否是后面的类型或者后面类型的子类类型,是返回true ,不是返回false。
- 强制类型可以解决多态的劣势,可以实现访问子类的独有功能。
1) 代码示例
package cn.utils;
// 基类
class People {
public void run(){
System.out.println("People可以跑步");
}
}
// 派生类:Student
class Student extends People {
@Override
public void run(){
System.out.println("Student跑的的贼溜..");
}
// 独有功能
public void study(){
System.out.println("学生要学习...");
}
}
// 派生类:Teacher
class Teacher extends People {
@Override
public void run(){
System.out.println("老师跑的的很快...");
}
// 独有功能
public void readBook(){
System.out.println("老师要看书...");
}
}
public class PolymorphicDemo01 {
public static void main(String[] args) {
// 创建p1对象
People p1 = new Student();
p1.run();
// 强制类型转换
Student st1 = (Student) p1;
st1.study();
System.out.println("======");
// 创建p2对象
People p2 = new Teacher();
// 强制类型转换
Teacher teacher1 = (Teacher) p2;
teacher1.readBook();
System.out.println("++++++");
People p3 = new Teacher();
// Cat ct = (Cat) a2; // 报错!
// 判断teacher2的真实类型是否是Teacher类型或者其子类类型。
if(p3 instanceof Teacher){
Teacher teacher2 = (Teacher) p3;
teacher2.readBook();
}else if(p3 instanceof Student){
Student st2 = (Student) p3;
st2.study();
}
}
}
2) 执行结果