当前位置: 首页 > article >正文

Java ---多态

(一)定义

官方:多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行不同操作。

生活中的多态,如图所示:

 

多态性是对象多种表现形式的体现。

现实中,比如我们想做榨果汁这个动作:

  • 如果用的是橙子,就会榨出橙汁 ;
  • 如果用的是西瓜,就会榨出西瓜汁 ;
  • 如果用的是蜜柚,就会榨出蜜柚汁 ;(有一说一,椰汁真的好喝)

简言之,多态:同一个事件发生在不同的对象上会产生不同的结果。

(二)多态的好处(为什么需要多态)&怎么实现多态

1.好处(意义) 

  • 消除类型之间的耦合关系
  • 可替换性
  •  可扩充性
  •  接口性
  •  灵活性
  •  简化性

简言之,多态使得代码的编写更灵活,功能更强大。更专业的答案是:可以实现虚方法的动态绑定

 2.多态的实现方式

  •    ① 重写:
  •    ② 接口: 生活中的接口最具代表性的就是插座,例如一个三接头的插头都能接在三孔插座中,因为这个是每个国家都有各自规定的接口规则,有可能到国外就不行,那是因为国外自己定义的接口类型。java中的接口类似于生活中的接口,就是一些方法特征的集合,但没有方法的实现。 
  • ③ 抽象类和抽象方法:

3.多态的用处 

   有时候,我们在设计一个数组、或一个成员变量、或一个方法的形参、返回值类型时,无法确定它具体的类型,只能确定它是某个系列的类型。

 具体:

  ① 声明变量是父类类型,变量赋值子类对象

  • 方法的形参是父类类型,调用方法的实参是子类对象

  • 实例变量声明父类类型,实际存储的是子类对象

②  数组元素是父类类型,元素对象是子类对象

③  方法返回值类型声明为父类类型,实际返回的是子类对象

(三)多态现象发生的前提

(1)继承
(2)有多态引用
    父类类型 变量 = 子类的对象;
变形:
    A:父类的类型[] 数组名 = new 父类的类型[长度];
        数组名[下标] = 子类的对象;
    B:形参的类型是父类的类型,实参是子类的对象
    C:方法的返回值类型是父类的类型,返回的实际结果是子类的对象
    D:某个成员变量声明的是父类的类型,实际接收的是子类对象
 总结:父类类型的变量/元素中存储了子类的对象(子类对象的首地址)
(3)通过多态引用的父类类型的变量/元素“调用虚方法”(虚方法:可以被子类“重写”的方法)。
        
       如果通过多态引用的父类类型的变量/元素调用的是非虚方法,或者是成员变量,那么不用考虑多态的问题,只看变量/元素的“编译时类型”。 

 具体代码:

public class CShape {
    //当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
    //多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。
     void draw(){
         System.out.println("画形状");
     }

    }
class Circle extends CShape {
    //
    void draw(){
        System.out.println("画圆形");
    }

}
class Square extends CShape {
    //
    void draw(){
        System.out.println("画矩形");
    }

}class Trapezoid extends CShape {
    //
    void draw(){
        System.out.println("画梯形");
    }

}

public class TestCC {
    public static void main(String args[]){

     CShape shape =new Circle();//向上转型
        shape.draw();
        Circle c=(Circle)shape;//向下转型
        c.draw();;
        print(new Circle());
        print(new Trapezoid());

    }
    public static void print(CShape ccc ){
       ccc.draw();
       //它是啥类型
       if(ccc instanceof  Circle){
           Circle c=(Circle) ccc;
            c.draw();
       }else if(ccc instanceof  Square){
           Square s=(Square)ccc;
           s.draw();
       }else if(ccc instanceof  Trapezoid ){
           Trapezoid t=(Trapezoid )ccc;
           t.draw();
       }
    }
}

(四)虚函数

 虚函数的存在是为了多态。

      Java 中其实没有虚函数的概念,它的普通函数就相当于 C++ 的虚函数,动态绑定是Java的默认行为。如果 Java 中不希望某个函数具有虚函数特性,可以加上 final 关键字变成非虚函数。

重写

我们将介绍在 Java 中,当设计类时,被重写的方法的行为怎样影响多态性。

 方法的重写即子类能够重写父类的方法。

当子类对象调用重写的方法时,调用的是子类的方法,而不是父类中被重写的方法。

要想调用父类中被重写的方法,则必须使用关键字 super

(五)金科玉律 

(1)面向对象的基本特征有哪些?

封装、继承、多态

(2)面向对象的特征有哪些?

封装、继承、多态、抽象

 (3)多态现象

    编译时看父类    运行时看子类
    如果子类重写的了“虚方法”,那么就一定执行的是重写后的代码。
    如果子类没有重写“虚方法”,那么还是执行父类中的方法体。

(4)变量/对象的类型
运行时类型:就是new关键字后面出现的类型名,从new出来之后,就不会改变。
编译时类型:可以变化的
    (1)当把对象赋值给一个父类变量/元素时,就会像上转型为父类类型
    (2)当把对象“向下转型”为子类类型时,就会转为子类类型
    (3)当然也可以手动的“向上转型”为父类的类型,即(父类类型)子类对象,也会转为父类类型
​如果调用的是虚方法,那么要关注的是对象的运行时类型。
如果调用的是非虚方法,或者成员变量,那么要关注的是对象的编译时类型。
(5)什么是编译时类型?

    1.对于变量来说,变量声明时,左边的类型就是它的编译时类型
    2.对于强制类型转换来说,()中写的类型是什么,它的编译时类型就是什么。如果有连续多次的强制类型转换,看最后一次。


http://www.kler.cn/a/7320.html

相关文章:

  • Shell中的函数
  • 电商系统开发:Spring Boot框架实战
  • 用pandoc工具实现ipynb,md,word,pdf之间的转化
  • Spring Boot 中 Druid 连接池与多数据源切换的方法
  • 2、开发工具和环境搭建
  • cache中setID和index
  • 利用CMake工具从源码编译出osgEarth库
  • Java基础——可变参数,集合操作工具类Collections
  • 【NLP入门教程】五、命名实体识别
  • 微服务学习-SpringCloud -Nacos (单机部署)
  • Windows 上使用 VS2022 使用远程Linux 系统调试运行代码
  • Linux中的算法分离手段
  • Git Commit Message 应该怎么写?
  • 【案例实践】MCM箱模型实践技术应用与O3形成途径、生成潜势、敏感性分析
  • 【创作赢红包】Activity初窥门径
  • C#,初学琼林(04)——查询(搜索)数组内指定(值)的元素与全文检索“倒排序”技术的实现代码源程序
  • OMG,太牛了!!!华为18级架构师总结出24W字Java面试手册
  • 伪数组和真数组的区别
  • 批发进销存管理软件,商品分类管理,对商品分类批量价格管理,商品分类导入导出的操作
  • acwing1047. 糖果
  • 技术宅小伙:看看面试官都问了些什么(Java系列)
  • SpringCloud服务注册中心——Eureka
  • 华为阿里版ChatGPT横空出世,谁的成效更好呢?
  • 【云原生进阶之容器】第五章容器运行时5.2节--容器运行时接口规范CRI
  • [论文速览] Sparks of Artificial General Intelligence: Early experiments with GPT-4
  • esxi的安装配置以及新建虚拟机