【多态】深入理解向上转型&向下转型

预备知识

面向对象编程--------理解多态
面向对象编程-------多态

向上转型

示例一

目录结构

在这里插入图片描述

原理&实现代码

在这里插入图片描述
老师专用门禁卡和学生专用门禁卡都继承了门禁卡。

AccessCard(父类:门禁卡)

package learn_extends.e1;

public class AccessCard {
    
    
    public void entrance() {
    
    
        System.out.println("验证身份,进出大门");
    }
}

StudentAccessCard(子类:学生专用门禁卡)

package learn_extends.e1;

public class StudentAccessCard extends AccessCard {
    
    
    @Override
    public void entrance() {
    
    
        super.entrance();
        System.out.println("同学们注意安全");
    }
}

TeacherAccessCard(子类:老师专用门禁卡)

package learn_extends.e1;

public class TeacherAccessCard extends AccessCard {
    
    
    @Override
    public void entrance() {
    
    
        super.entrance();
        System.out.println("欢迎 XXX 老师");
    }
}

Main

package learn_extends.e1;

public class Main {
    
    
    public static AccessCard[] createCardArray() {
    
    
        AccessCard[] array = new AccessCard[10];

        for (int i = 0; i < 5; i++) {
    
    
            AccessCard o = new StudentAccessCard();        // 向上转型
            array[i] = o;
        }

        for (int i = 5; i < 10; i++) {
    
    
            AccessCard o = new TeacherAccessCard();        // 向上转型
            array[i] = o;
        }

        return array;
    }

    // 相同的东西,表现不同的形态 —— 多态
    public static void main(String[] args) {
    
    
        AccessCard[] array = createCardArray();

        for (AccessCard o : array) {
    
    
            // 目前 o 指向的对象,可能是老师专用的 OR 学生专用的
            o.entrance();   // 跟着对象类型走
                            // 前 5 个是学生,后 5 个是老师
            System.out.println("=========================");
        }
    }
}

AccessCard o = new StudentAccessCard(); 
AccessCard o = new TeacherAccessCard();   

在这里发生了向上转型,引用都是父类的引用,对象不同,执行entrance()方法是,根据子类重写了父类的该方法,最后执行的结果就不同了。

运行结果

在这里插入图片描述

示例二

目录结构

在这里插入图片描述

原理分析&代码实现

在这里插入图片描述
Person

package learn_extends.e2;

public class Person {
    
    
    public String getName() {
    
    
        return "person";
    }
}

Teacher

package learn_extends.e2;

public class Teacher extends Person {
    
    
    public void teach() {
    
    
        System.out.println("教学中 ...");
    }
}

MathTeacher

package learn_extends.e2;

public class MathTeacher extends Teacher {
    
    
    @Override
    public String getName() {
    
    
        return "math:" + super.getName();
    }

    @Override
    public void teach() {
    
    
        System.out.println("我是数学老师");
        super.teach();
    }

    public void draw() {
    
    
        System.out.println("画图形");
    }
}

EnglishTeacher

package learn_extends.e2;

public class EnglishTeacher extends Teacher {
    
    
    @Override
    public String getName() {
    
    
        return "english:" + super.getName();
    }

    @Override
    public void teach() {
    
    
        System.out.println("我是英语老师");
        super.teach();
    }

    public void speak() {
    
    
        System.out.println("听说读写");
    }
}

Main

package learn_extends.e2;

public class Main {
    
    
    private static MathTeacher createObject() {
    
    
        return new MathTeacher();
    }

    public static void main(String[] args) {
    
    
        Person p = createObject();

        System.out.println(p.getName());
        //p.teach();
        //p.draw();
    }
}

下边我们来分析一下:
在这里插入图片描述
父类引用是Person,决定了它所能执行的方法Person.java 父类中只有getName方法,所以p引用只能.出getName,虽然MathTeacher中还有techerdraw方法,但是都不能执行。
在这里插入图片描述
我们再来看调用getName方法后执行那个代码呢,因为对象是MathTeacher
其中还重写了父类的该方法,所以就先在子类中找,刚好有就执行重写后的代码:
在这里插入图片描述
结果为:
在这里插入图片描述

刚才说到techerdraw方法不能执行,是因为引用是Person,那么如果把引用改为MathTeacher 就可以了。
在这里插入图片描述
所以说引用类型控制了执行方法的权限,而对象类型可以控制到底执行那个方法
代码分析结果如下:

引用类型 p = new 对象类型 p.方法 是否可执行 执行结果
Person p = new Person() p.getName() person
Person p = new Person() p.teach() ×
Person p = new Person() p.draw() ×
Person p = new Person() p.speak() ×
Person p = new MathTeacher() p.getName() math:person
Person p = new MathTeacher() p.teach() ×
Person p = new MathTeacher() p.draw() ×
Person p = new MathTeacher() p.speak() ×
Person p = new EnglishTeacher p.getName() english:person
Person p = new EnglishTeacher p.teach() ×
Person p = new EnglishTeacher p.draw() ×
Person p = new EnglishTeacher p.speak() ×
MathTeacher p = new MathTeacher() p.getName() math:person
MathTeacher p = new MathTeacher() p.teach() 我是数学老师 教学中 …
MathTeacher p = new MathTeacher() p.draw() 画图形
MathTeacher p = new MathTeacher() p.speak() ×
EnglishTeacher p = new EnglishTeacher p.getName() english:person
EnglishTeacher p = new EnglishTeacher p.teach() 我是英语老师 教学中 …
EnglishTeacher p = new EnglishTeacher p.draw() ×
EnglishTeacher p = new EnglishTeacher p.speak() 听说读写

向下转型

需求分析

在这里插入图片描述

示例三

目录结构

在这里插入图片描述

代码

Person

package learn_extends.e3;

public class Person {
    
    
}

Doctor

package learn_extends.e3;

public class Doctor extends Person {
    
    
    public void rescue() {
    
    
        System.out.println("进行心肺复苏");
    }
}

Student

package learn_extends.e3;

public class Student extends Person {
    
    
    public void learn() {
    
    
        System.out.println("好好学习,天天向上");
    }
}

Teacher

package learn_extends.e3;

public class Teacher extends Person {
    
    
    public void teach() {
    
    
        System.out.println("我在讲课");
    }
}

Main

package learn_extends.e3;

import javax.print.Doc;

public class Main {
    
    
    private static Person[] train() {
    
    
        Person[] array = new Person[10];
        for (int i = 0; i < 5; i++) {
    
    
            array[i] = new Teacher();
        }
        array[5] = new Doctor();
        for (int i = 6; i < 10; i++) {
    
    
            array[i] = new Student();
        }

        return array;
    }

    public static void main(String[] args) {
    
    
        Person[] array = train();

        for (int i = 0; i < array.length; i++) {
    
    
            Person p = array[i];
            if (p instanceof Doctor) {
    
    
                System.out.println("下标是 " + i + " 的乘客是医生");
                Doctor d = (Doctor)p;
                d.rescue();
            } else {
    
    
                //System.out.println("不是医生,冒充医生");
                //Doctor d = (Doctor)p;
                //d.rescue();
            }
        }
    }
}

结果

在这里插入图片描述
不是医生就会类型转换报错:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45532227/article/details/113357379