• 67-Java面向对象三大特征之三:多态


    一、面向对象三大特征之三:多态

    1、多态是什么?

    • 同类型的对象,执行同一个行为,会表现出不同的行为特征。
      • 比如:猫和狗都是动物类型,执行同一个行为,但是会表现出不同的行为特征;

    2、多态的常见形式

    父类类型 对象名称 = new 子类构造器;
    接口 对象名称 = new 实现类构造器;
    
    • 1
    • 2
    package com.app.d1_polymorphism;
    
    /**
        动物类:父类——抽象类
     */
    public abstract class Animal {
        public abstract void run();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    package com.app.d1_polymorphism;
    
    /**
        狗类:子类,继承动物类
     */
    public class Dog extends Animal{
        @Override
        public void run() {
            System.out.println("🐕跑得很快~~");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    package com.app.d1_polymorphism;
    
    /**
        乌龟类:子类,继承动物类
     */
    public class Tortoise extends Animal{
        @Override
        public void run() {
            System.out.println("🐢跑不起来!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    package com.app.d1_polymorphism;
    
    /**
        目标:认识多态,理解多态的形式和概念
     */
    public class PolymorphismTest {
        public static void main(String[] args) {
    //         以前的形式
            Dog d1 = new Dog();
            d1.run();
    
            Tortoise t1 = new Tortoise();
            t1.run();
            System.out.println("---------------------------------");
    
    //         1、多态的形式:父类类型 对象名称 = new 子类构造器;
            // 其实多态的这个形式就是:右边的狗对象 赋值给 左边的动物对象
            // 狗对象只代表一种动物;动物对象代表所有的动物。属于小范围的 赋值给 大范围的,合情合理!
            Animal d2 = new Dog();
            d2.run();
    
            Tortoise t2 = new Tortoise();
            t2.run();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    🐕跑得很快~~
    🐢跑不起来!
    ---------------------------------
    🐕跑得很快~~
    🐢跑不起来!
    
    Process finished with exit code 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7


    3、多态中成员访问特点

    • 方法调用:编译看左边,运行看右边;
      在这里插入图片描述

    • 变量调用:编译看左边,运行也看左边。多态侧重行为多态
      在这里插入图片描述

    在这里插入图片描述


    在这里插入图片描述


    在这里插入图片描述


    4、多态的前提

    • 有继承/实现关系;有父类引用指向子类对象;有方法重写。


    二、多态的优势

    1、优势

    (1)在多态形式下,右边对象可以实现解耦合,便于扩展和维护

    • 没换掉之前
      在这里插入图片描述在这里插入图片描述


    • 换掉之后,run行为也会随着对象而变,不需要改动代码

    在这里插入图片描述


    • 解耦合: 什么意思呢?

      • 举例说明:
        • 比如你家孩子买了一个变形金刚的玩具,玩着玩着没电了,这时候只需要换电池,就可以继续玩;
        • 再比如你买了一辆电动车,哪天轮胎爆了,这时候只需要去维修店换轮胎,是不是就可以继续开了。

    (2)定义方法的时候,使用父类型作为参数,该方法就可以接收这个父类的一切子类对象,体现出多态的扩展与便利

    • 所有动物参加赛跑比赛
      在这里插入图片描述


    • 执行原理:
      在这里插入图片描述


    2、多态下产生的问题

    • 多态下不能使用子类的独有功能

      • 因为父类是被继承的,因此继承了父类的子类会有父类的一切行为,但是父类是没有子类独有行为的。
        在这里插入图片描述


        在这里插入图片描述


        在这里插入图片描述

    三、多态下引用类型的类型转换

    1、引用类型是什么?

    • 也就是我们自己定义的:动物类、学生类、猫类、老师类等等。

    2、引用类型的类型转换

    • 自动类型转换(从子到父):子类对象赋值给父类类型的变量指向。

      • 因为父类范围大,所有子类对象赋值给父类类型的变量指向—>属于:小范围 赋值给 大范围,因此是自动类型转换
    • 强制类型转换(从父到子)

      • 此时必须进行强制类型转换:

        子类 对象变量 = (子类)父类类型的变量;
        
        • 1
      • 作用:可以解决多态下的劣势,可以实现调用子类的独有行为(方法功能)。
        在这里插入图片描述


        在这里插入图片描述


        在这里插入图片描述


        在这里插入图片描述



        在这里插入图片描述

      • 注意:如果 转型后的类型 和对象真实类型 不是同一种类型,那么在转换的时候就会出现 ClassCastException
        在这里插入图片描述
        在这里插入图片描述


    3、instanceof关键字

    • Java建议多态下的引用类型在强制类型转换的前,使用 instanceof 关键字判断当前对象的真实类型,再进行强制类型转换。

      变量名 instanceof 真实类型
      判断 instanceof 左边的变量指向的对象的真实类型,是否与右边的类型或者与其子类类型一样,是则返回true,反之。
      
      • 1
      • 2

    在这里插入图片描述



    在这里插入图片描述



    4、知识总结

    1、引用类型的类型转换,有几种方式?

    • 有自动类型转换、强制类型转换

    2、强制类型转换能解决什么问题?需要注意什么?

    • 可以解决多态下不能访问子类独有功能的问题,强制转换后可以访问
    • 有继承或者实现关系的两个类型就可以进行强制转换,编译无问题
    • 运行时,如果发现强制转换后的类型不是对象的真实类型则会报错
    • 注意:java建议强制转换前使用 instanceof 关键字判断一下当前对象的真实类型,再进行强制类型转换


    四、多态综合案例

    1、案例一

    此案例,无实际含义,目的是为了通过此案例理解之前所学的语法

    • 需求:

      • 使用面向对象编程模拟:设计一个电脑对象,可以安装2个USB设备;

      • 鼠标:被安装时可以完成接入、调用点击、拔出功能;

      • 键盘:被安装时可以完成接入、调用打字、拔出功能。

    • 分析实现:

      • 1、定义一个USB的接口:(申明USB设备的规范必须是:可以接入、拔出);

      • 2、定义2个USB实现类代表鼠标、键盘,让其实现USB接口,并分别定义它们自己独有的功能;

      • 3、创建电脑对象,创建2个USB实现类对象,分别安装到电脑中并触发功能的执行。

      • USB接口

        package com.app.d4_polymorphism_test;
        
        /**
            1、定义一个USB的接口:(申明USB设备的规范必须是:可以接入、拔出);
         */
        public interface USB {
            void access();  // 接入
            void pullOut(); // 拔出
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9

      • 键盘实现类

        package com.app.d4_polymorphism_test;
        
        /**
            2、定义USB实现类代表键盘,让其实现USB接口
         */
        public class KeyBoard implements USB{
            /**
                b、定义键盘名称:商标
             */
            private String keyBoardName;
        
        
            /**
                c、提供无参、有参构造器
             */
            public KeyBoard() {
        
            }
        
            public KeyBoard(String keyBoardName) {
                this.keyBoardName = keyBoardName;
            }
        
        
            /**
                d、提供变量对应的getter、setter方法,暴露其取值和赋值
             */
            public String getKeyBoardName() {
                return keyBoardName;
            }
        
            public void setKeyBoardName(String keyBoardName) {
                this.keyBoardName = keyBoardName;
            }
        
        
            /**
                a、实现USB接口的规范:接入、拔出
             */
            @Override
            public void access() {
                System.out.println(keyBoardName + "已成功连接电脑~");
            }
        
            @Override
            public void pullOut() {
                System.out.println(keyBoardName + "已安全拔出电脑~");
            }
        
        
            /**
                e、并定义它自己独有的功能:打字
             */
            public void tap() {
                System.out.println(keyBoardName + "敲击了:老铁,没毛病~~ 666~~~");
            }
        
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
      • 鼠标实现类

        package com.app.d4_polymorphism_test;
        
        /**
            2、定义USB实现类代表鼠标,让其实现USB接口
         */
        public class Mouse implements USB{
            /**
                b、定义鼠标名称:商标
             */
            private String mouseName;
        
        
            /**
                c、提供无参、有参构造器
             */
            public Mouse() {
        
            }
        
            public Mouse(String mouseName) {
                this.mouseName = mouseName;
            }
        
        
            /**
                d、提供变量对应的getter、setter方法,暴露其取值和赋值
             */
            public String getMouseName() {
                return mouseName;
            }
        
            public void setMouseName(String mouseName) {
                this.mouseName = mouseName;
            }
        
        
            /**
                a、实现USB接口的规范:接入、拔出
             */
            @Override
            public void access() {
                System.out.println(mouseName + "已成功连接电脑~");
            }
        
            @Override
            public void pullOut() {
                System.out.println(mouseName + "已安全拔出电脑~");
            }
        
        
            /**
                e、并定义它自己独有的功能:点击
             */
            public void click() {
                System.out.println(mouseName + "点击了屏幕~");
            }
        
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
      • 电脑类

        package com.app.d4_polymorphism_test;
        
        /**
            3、创建电脑对象:计算机类
         */
        public class Computer {
            /**
                a、定义计算机名称:商标
             */
            private String computerName;
        
            /**
                b、提供有参和无参构造器
             */
            public Computer() {
            }
        
            public Computer(String computerName) {
                this.computerName = computerName;
            }
        
            /**
                c、提供变量对应的getter、setter方法,暴露其取值和赋值
             */
            public String getComputerName() {
                return computerName;
            }
        
            public void setComputerName(String computerName) {
                this.computerName = computerName;
            }
        
        
            /**
                模拟电脑开机
             */
            public void start(){
                System.out.println(computerName + "开机了~");
            }
        
            /**
                d、提供安装USB时的入口
             */
            public void installUSB(USB usb){
                // USB设备连接电脑
                usb.access();
        
                // usb 有可能是键盘,也有可能是鼠标
                // 在接入时,先判读这个设备是键盘还是鼠标
                if (usb instanceof KeyBoard) {
                    // 是键盘,将USB强制转换成键盘
                    KeyBoard k = (KeyBoard) usb;
                    k.tap();
        
                }else if (usb instanceof Mouse) {
                    // 是鼠标,将USB强制转换成鼠标
                    Mouse m = (Mouse) usb;
                    m.click();
                }
        
                // USB设备安全拔出电脑
                usb.pullOut();
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59
        • 60
        • 61
        • 62
        • 63
        • 64
      • 测试类

        package com.app.d4_polymorphism_test;
        
        /**
            目标:USB设备模拟。
            通过此案例综合起之前所学的语法,训练面向对象的思维。
        
            需求:
                使用面向对象编程模拟:设计一个电脑对象,可以安装2个USB设备;
                鼠标:被安装时可以完成接入、调用点击、拔出功能;
                键盘:被安装时可以完成接入、调用打字、拔出功能。
         */
        public class Test {
            public static void main(String[] args) {
                // a、创建电脑对象
                Computer c1 = new Computer("联想电脑");
                // b、开机
                c1.start();
        
                // c、创建键盘、鼠标对象
                USB u1 = new KeyBoard("雷蛇");
                USB u2 = new Mouse("罗技鼠标");
        
                // d、连接电脑
                c1.installUSB(u1);
                c1.installUSB(u2);
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
      • 控制台

        联想电脑开机了~
        雷蛇已成功连接电脑~
        雷蛇敲击了:老铁,没毛病~~ 666~~~
        雷蛇已安全拔出电脑~
        罗技鼠标已成功连接电脑~
        罗技鼠标点击了屏幕~
        罗技鼠标已安全拔出电脑~
        
        Process finished with exit code 0
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
  • 相关阅读:
    c#中的接口
    2022/11/18[指针] 关于指针的初步理解
    128-根据给定的字符串,建立二叉树
    搭建STM32F407的SPI-Flash(基于STM32CubeMX)
    第二章 C API稳定性
    什么是Ribbon的饥饿加载?有什么优势?
    camera项目相关路径
    电子元器件包装类型
    微信小程序,制作属于自己的Icon图标
    如何实现机器人自动拉微信群
  • 原文地址:https://blog.csdn.net/yelitoudu/article/details/126105766