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


    目录

    1.多态的概述,多态的形式

    说明是多态?

    多态的常见形式

    多态中成员访问特点

    多态的前提

    2.多态的优势

    优势:

    3.多态下引用数据类型的类型转换(实现在多态的情况下可以调用子类的独特功能)


    1.多态的概述,多态的形式

    说明是多态?

    同类型的对象,执行同一个行为,会表现出不同的行为特征。

    多态的常见形式

    父类类型 对象名称 = new 子类构造器;

    接口         对象名称 = new 实现类构造器;

    1. public class Test {
    2. public static void main(String[] args) {
    3. // 目标:先认识多态的形式
    4. // 父类 对象名称 = new 子类构造器();
    5. Animal a = new Dog();
    6. a.run(); // 方法调用:编译看左,运行看右
    7. System.out.println(a.name); // 变量调用调用:编译看左,运行也看左,动物名称
    8. Animal a1 = new Dog();
    9. a1.run();
    10. System.out.println(a1.name); // 动物名称
    11. }
    12. }

    多态中成员访问特点

    方法调用:编译看左边,运行看右边;

    变量调用:编译看左边,运行也看左边。(多态侧重行为多态

    多态的前提

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

    2.多态的优势

    优势:

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

    例如:

    1. Animal a = new Dog();
    2. a.run();

    当new Dog这个对象改变时,后续的业务行为也会随着改对象改变,那么后续的代码无需修改。

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

    多态下会产生一个问题:

    多态下不能使用子类独有功能,例如:

    1. public class Animal {
    2. public String name = "动物名称";
    3. public void run(){
    4. System.out.println("动物可以跑~~");
    5. }
    6. }
    1. public class Dog extends Animal {
    2. public String name = "狗名称";
    3. @Override
    4. public void run() {
    5. System.out.println("🐕跑的贼溜~~~~~");
    6. }
    7. /**
    8. 独有功能
    9. */
    10. public void lookDoor(){
    11. System.out.println("🐕在看🚪!!!");
    12. }
    13. }
    1. public class Tortoise extends Animal {
    2. public String name = "乌龟名称";
    3. @Override
    4. public void run() {
    5. System.out.println("🐢跑的非常慢~~~");
    6. }
    7. }
    1. public class Test {
    2. public static void main(String[] args) {
    3. Animal d = new Dog();
    4. go(d);
    5. // d.lookDoor();
    6. Animal t = new Tortoise();
    7. go(t);
    8. }
    9. /**
    10. 希望这个方法可以接收一切子类动物对象
    11. * @param a
    12. */
    13. public static void go(Animal a){
    14. System.out.println("预备~~~");
    15. a.run();
    16. System.out.println("结束~~~~");
    17. }
    18. }

    3.多态下引用数据类型的类型转换(实现在多态的情况下可以调用子类的独特功能)

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

    强制类型转换(从父到子)

    1.此时必须进行强制类型转换:子类 对象变量 = (子类)父类类型的变量;

    2.作用:可以解决多态下的劣势,可以实现调用子类独有的功能;

    3.注意:如果转换后的类型和对象真实类型不是同一种类型,那么在转换的时候就会出现ClassCastException

    java建议强转转换前使用instanceof判断当前对象的真实类型,再进行强制转换。

    变量名 instanceof 真实类型

    判断关键字左边的变量指向的对象的真实类型,是否是右边的类型或者是其子类类型,是则返回true,反之false。

    1. public class Animal {
    2. public String name = "动物名称";
    3. public void run(){
    4. System.out.println("动物可以跑~~");
    5. }
    6. }
    1. public class Dog extends Animal {
    2. public String name = "狗名称";
    3. @Override
    4. public void run() {
    5. System.out.println("🐕跑的贼溜~~~~~");
    6. }
    7. /**
    8. 独有功能
    9. */
    10. public void lookDoor(){
    11. System.out.println("🐕在看🚪!!!");
    12. }
    13. }
    1. public class Tortoise extends Animal {
    2. public String name = "乌龟名称";
    3. @Override
    4. public void run() {
    5. System.out.println("🐢跑的非常慢~~~");
    6. }
    7. /**
    8. 独有功能
    9. */
    10. public void layEggs(){
    11. System.out.println("🐢在下蛋~~~");
    12. }
    13. }
    1. public class Test {
    2. public static void main(String[] args) {
    3. // 自动类型转换
    4. Animal a = new Dog();
    5. a.run();
    6. // a.lookDoor(); // 多态下无法调用子类独有功能
    7. // 强制类型转换:可以实现调用子类独有功能的
    8. Dog d = (Dog) a;
    9. d.lookDoor();
    10. // 注意:多态下直接强制类型转换,可能出现类型转换异常
    11. // 规定:有继承或者实现关系的2个类型就可以强制类型转换,运行时可能出现问题。
    12. // Tortoise t1 = (Tortoise) a;
    13. // 建议强制转换前,先判断变量指向对象的真实类型,再强制类型转换。
    14. if(a instanceof Tortoise){
    15. Tortoise t = (Tortoise) a;
    16. t.layEggs();
    17. }else if(a instanceof Dog){
    18. Dog d1 = (Dog) a;
    19. d1.lookDoor();
    20. }
    21. System.out.println("---------------------");
    22. Animal a1 = new Dog();
    23. go(a1);
    24. }
    25. public static void go(Animal a){
    26. System.out.println("预备~~~");
    27. a.run();
    28. // 独有功能
    29. if(a instanceof Tortoise){
    30. Tortoise t = (Tortoise) a;
    31. t.layEggs();
    32. }else if(a instanceof Dog){
    33. Dog d1 = (Dog) a;
    34. d1.lookDoor();
    35. }
    36. System.out.println("结束~~~~");
    37. }
    38. }

    4.多态的案例

    需求:

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

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

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

    分析:

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

    2.提供2个USB实现类代表鼠标和键盘,让其实现USB接口,并分别定义独有功能。

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

    1. public class Computer {
    2. /**
    3. 提供一个安装的入口:行为。
    4. */
    5. public void installUSB(USB u){
    6. u.connect();
    7. // 独有功能
    8. if(u instanceof Mouse){
    9. Mouse m = (Mouse) u;
    10. m.click();
    11. }else if(u instanceof KeyBoard) {
    12. KeyBoard k = (KeyBoard) u;
    13. k.keyDown();
    14. }
    15. u.unconnect();
    16. }
    17. }
    1. public class KeyBoard implements USB{
    2. private String name;
    3. public KeyBoard(String name) {
    4. this.name = name;
    5. }
    6. @Override
    7. public void connect() {
    8. System.out.println(name + "成功的接入了设备了~~~");
    9. }
    10. @Override
    11. public void unconnect() {
    12. System.out.println(name + "成功的从设备弹出了~~~");
    13. }
    14. /**
    15. 独有功能
    16. */
    17. public void keyDown(){
    18. System.out.println(name + "写下了:老铁,6666,下次再来哦,老弟~~~~");
    19. }
    20. public String getName() {
    21. return name;
    22. }
    23. public void setName(String name) {
    24. this.name = name;
    25. }
    26. }
    1. public class Mouse implements USB{
    2. private String name;
    3. public Mouse(String name) {
    4. this.name = name;
    5. }
    6. @Override
    7. public void connect() {
    8. System.out.println(name + "成功的接入了设备了~~~");
    9. }
    10. @Override
    11. public void unconnect() {
    12. System.out.println(name + "成功的从设备弹出了~~~");
    13. }
    14. /**
    15. 独有功能
    16. */
    17. public void click(){
    18. System.out.println(name + "双击点亮小红心~~~~");
    19. }
    20. public String getName() {
    21. return name;
    22. }
    23. public void setName(String name) {
    24. this.name = name;
    25. }
    26. }
    1. public class Test {
    2. public static void main(String[] args) {
    3. // a、创建电脑对象
    4. Computer c = new Computer();
    5. // b、创建USB设备对象
    6. USB u = new Mouse("罗技鼠标");
    7. c.installUSB(u);
    8. USB k = new KeyBoard("双飞燕键盘");
    9. c.installUSB(k);
    10. }
    11. }
    1. public interface USB {
    2. void connect();
    3. void unconnect();
    4. }

  • 相关阅读:
    【力扣刷题】只出现一次的数字
    idea显示git分支信息(GitToolBox插件)
    没有不写注释的程序员,如果有,一定没看过别人的代码?
    Flutter 实现“斑马纹”背景(需要变换颜色)
    wvp平台 视频设备接入注意点
    基于Java的设计模式 - 代理模式
    Qt 开发使用VSCode
    基于I/Q数据的5G控制信道盲检
    异步FIFO设计
    LeetCode #94.二叉树的中序遍历
  • 原文地址:https://blog.csdn.net/weixin_65440201/article/details/125463084