Java-多态

目录

1.多态的概念

2.多态的实现条件。

3.重写

4.向上转型和向下转型

5.多态的优缺点

6.避免在构造方法中调用重写方法


1.多态的概念

        多态字面意思就是多种形态,具体点就是完成某个行为时,不同的对象完成时产生不同的状态。

         总之,同一件事情,发生在不同的对象身上,会有不同的结果

2.多态的实现条件。

        在java中要实现多态,必须要满足如下几个条件,缺一不可:

                1. 继承关系上:向上转型

                2. 子类有和父类同名的重写方法

                3.  通过父类对象的引用,调用重写的方法

       完成以上三个条件,就会发生动态绑定,动态绑定是多态的基础。

        多态的体现:在代码运行时,传递不同类对象时,会调用对应类中的重写方法。

class Animals{

    public String name;

    public int age;

    public Animals(String name,int age){

        this.name=name;

        this.age=age;

 }

    public void eat(){

        System.out.println(this.name+"正在吃饭");

    }

}

class Dogs extends Animals{

    public Dogs(String name, int age){

        super(name,age);

    }

    public void bark(){

        System.out.println(this.name+"正在汪汪叫~");

    }

    //方法重写

    @Override  //注解

    public void eat() {

        System.out.println(this.name+"正在吃狗粮");

    }

}

class Cats extends Animals{

    public Cats(String name, int age){

        super(name,age);

    }

    public  void mimi(){

        System.out.println(this.name+"正在喵喵叫~");

    }

    //方法重写

    @Override  //注解

    public void eat() {

        System.out.println(this.name+"正在吃猫粮");

    }

}

public class Text {

        public static void main(String[] args) {

        //animal这个引用 指向了Dogs类的对象,向上转型直接赋值

        Animals animal=new Dogs("赛虎",10);

        animal.eat();//父类的eat

        System.out.println("====");

        //animal这个引用 指向了Cats类的对象,向上转型直接赋值

        Animals animal1=new Cats("菲菲",15);

        animal1.eat();

    }

}

与上述代码中向上转型方式不同,但原理相同。

3.重写

        重写(override):也称为覆盖。重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程进行重新编写, 返回值和形参都不能改变即外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。

public void eat(){
    System.out.println(this.name+"正在吃饭");
}

public void eat() {
    System.out.println(this.name+"正在吃狗粮");
}
public void eat() {
    System.out.println(this.name+"正在吃猫粮");
}


        重写规则

        1.一般最基本的:返回值、参数列表、方法名必须一样

        2.被重写的方法的访问修饰限定符在子类中要大于等于在父类中的,即访问权限不能比父类中被重写的方法的访问权限更低,例如如果父类方法被public修饰,则子类中重写该方法就不能声明为 protected。

        3.父类被static、private,final修饰的方法、构造方法都不能被重写。

        4.重写的方法, 可以使用 @Override 注解来显式指定. 有了这个注解能帮我们进行一些合法性校验。

         方法重载(overloading)是一个类的多态性表现,而方法重写(overriding)是子类与父类的一种多态性表现。

         重写设计原则:对于已经投入使用的类,尽量不要进行修改。最好的方式是:重新定义一个新的类,来重复利用其中共性的内容,并且添加或者改动新的内容

        例如:几十年前的手机,只能打电话,发短信,来电显示只能显示号码,而今天的手机在来电显示的时候,不仅仅可以显示号码,还可以显示头像,地区等。在这个过程当中,我们不应该在原来老的类上进行修改,因为原来的类,可能还在有用户使用,正确做法是:新建一个新手机的类,对来电显示这个方法重写就好了,这样就达到了我们当今的需求了。
        静态绑定:也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代表方法重载。
        动态绑定:也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用那个类的方法

4.向上转型和向下转型

        

       1. 向上转型:实际就是创建一个子类对象,将其当成父类对象来使用。
        语法格式:父类类型 对象名=new 子类类型()

        Animal animal=new Dogs(“赛虎”,10);

         animal是父类类型,但可以引用一个子类对象,因为是从小范围向大范围的转换。

        向上转型方法:1直接赋值2.方法的参数,传参时向上赋值3.返回值向上转型。

        1.直接赋值

Animal animal=new Dogs(“赛虎”,10);

        2.方法的参数,传参时向上转型

//方法的参数,传参的时候向上转型
public static void func1(Animals animal) {
    
}
public static void main2(String[] args) {
    Dogs dog=new Dogs("赛虎",10);
    func1(dog);
}

         3.返回值向上转型

        //3.返回值 向上转型
public static Animals main3(String[] args){
    Dogs dog=new Dogs("赛虎",10);
    return dog;
}

         向上转型的优点:让代码实现更简单灵活,,缺点:不能调用到子类特有的方法
        2. 向下转型:将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的方法,此时:将父类引用再还原为子类对象即可
 

 Java中为了提高向下转型的安全性,引入了 instanceof ,如果该表达式为true,则可以安全转换。

public class Text {

        public static void main(String[] args) {

        //animal这个引用 指向了Dogs类的对象,向上转型直接赋值

        Animals animal=new Dogs("赛虎",10);

        animal.eat();//父类的eat

        System.out.println("====");

        //animal这个引用 指向了Cats类的对象,向上转型直接赋值

        animal=new Cats("菲菲",15);

        animal1.eat();

        //表示如果引用animal指向对象类型确实为Dogs对象实例

        if(animal instanceof Dogs){

                dog=(Dog)animal;

        }

        //表示如果引用animal指向对象类型确实为Cat对象实例

        if(animal instanceof Dogs){

                cat=(Cat)animal;

        }

    }

}

5.多态的优缺点

        若有以下代码

class Shape{
    public void drow(){
        System.out.println("画一个图案");
    }
}
//矩形
class Rect extends Shape{

    @Override
    public void drow() {
        System.out.println("矩形!~~~");
    }
}
//圆形
class Cycle extends Shape{
    @Override
    public void drow() {
        System.out.println("圆形⚪!~~~");
    }
}
//花形
class Flower extends Shape{
    @Override
    public void drow() {
        System.out.println("花形❀!~~~");
    }
}

        使用多态的好处:

            1.能够降低代码的 "圈复杂度", 避免使用大量的 if - else。

                圈复杂度是一种描述一段代码复杂程度的方式. 一段代码如果平铺直叙, 那么就比较简单容易理解. 而如果有很多的条件分支或者循环语句, 就认为理解起来更复杂,我们可以简单粗暴的计算一段代码中条件语句和循环语句出现的个数, 这个个数就称为 "圈复杂度"。如果一个方法的圈复杂度太高, 就需要考虑重构。

        现在我们需要打印多个形状:

        不基于多态实现方法

public class Textshape {

        public static void main(String[] args) {

                Cycle cycle=new Cycle();

                Rect rect=new Rect();

                Flower flower=new Flower();

                String[] shapes={"cycle","rect","flower"}

                for(Sting shape:shapes){

                        if(shape.equals(''cycle")){

                                cycle.drow();

                        }

                       else if(shape.equals(''rect")){

                                rect.drow();

                        }

                        else if(shape.equals(''flower")){

                                flower.drow();

                        }

                }

}

        基于多态的实现方法

public class Textshape {
    public static void funshape(Shape shape){
        shape.drow();
    }
    public static void main(String[] args) {
        /*Shape shape1=new Cycle();  //直接赋值向上转型
        Shape shape2=new Rect();
        Shape shape3=new Flower();
        shape1.drow();
        shape2.drow();
        shape3.drow();*/

        /*Cycle cycle=new Cycle();
        Rect rect=new Rect();
        Flower flower=new Flower();
        funshape(cycle);  //方法传参向上转型
        funshape(rect);
        funshape(flower);*/

        //创建了Shape对象的数组
        Shape[] shapes={new Cycle(),new Rect(),new Flower()}
        for(Shape x:shapes){
                shape.drow();
        }
    }
}

         2.可扩展能力强

        如果要新增一种新的形状, 使用多态的方式代码改动成本也比较低。

class Triangle extends Shape {
        @Override
        public void draw() {
        System.out.println("△");
        }
}

        多态缺陷:代码的运行效率降低
        1.属性没有多态性。当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性。
        2.构造方法没有多态性。

6.避免在构造方法中调用重写方法

        一段有坑的代码,创建两个类, B 是父类, D 是子类. D 中重写 func 方法. 并且在 B 的构造方法中调用 func。

class B{

        public B(){

                func();

        }

        public void func(){

                System.out.println("B.func()");

        }

}

class D extends B{

        private int num=1;

        @Override
        public void func() {
                System.out.println("D.func() " + num);
        }

}

public class Text {
    public static void main(String[] args) {
        D d = new D();
    }
}

        构造 D 对象的同时, 会调用 B 的构造方法;B 的构造方法中调用了 func 方法, 此时会触发动态绑定, 会调用到 D 中的 func此时 D 对象自身还没有构造, 此时 num 处在未初始化的状态, 值为 0; 如果具备多态性,num的值应该是1;所以在构造函数内,尽量避免使用实例方法,除了final和private方法。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/57345.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

uniapp运行项目到iOS基座

2022年9月,因收到苹果公司警告,目前开发者已无法在iOS真机设备使用未签名的标准基座,所以现在要运行到 IOS ,也需要进行签名。 Windows系统,HBuilderX 3.6.20以下版本,无法像MacOSX那样对标准基座进行签名…

JavaSE【继承和多态】(2)(向上转型、向下转型、重写、动态绑定、静态绑定、多态的运用)

一、多态 1.多态的概念 多态的概念:通俗来说,就是多种形态, 具体点就是去完成某个行为,当不同的对象去完成时会产生出不同 的状 态。 简单说就是,同一件事情,发生在不同对象身上,就会产生不同…

Mac强制停止应用

有时候使用Mac的时候,某个应用卡住了,但是肯定不能因为一个应用卡住了, 就将电脑重启吧,所以只需要单独停止该应用即可,使用快捷键optioncommandesc就会出现强制停止的界面,选择所要停止的应用,…

如何解决跨域问题?

一,什么是跨域 域(Origin)是由协议、域名和端口组成的,只有这三者完全一致的情况下,浏览器才会认为两个网址同源,否则就认为存在跨域。跨域是指在Web开发中,一个网页的JavaScript代码试图访问另…

yolov8-制作数据集,数据集格式转换(yolo格式-voc格式)附完整代码

yolo训练时可使用的数据集格式为yolo格式以及voc格式, voc格式的数据集在训练时需要先转换为yolo格式,然后根据自己的数据集的位置更改yaml配置文件的文件路径即可。基于目前对Yolo系列训练模型的讲解已经很全面,所以本文主要讲解yolo数据集与…

aws中opensearch 日志通(Centralized Logging with OpenSearch)2.0(一)

aws日志通2.0 实现全面的日志管理和分析功能 一体化日志摄取 :把aws服务器日志和应用日志传输到opensearch域中无代码日志处理 :在网页控制台中就可以实现数据处理开箱即用 :提供可视化模版(nginx、HTTP server ) 架构…

如何有效保障企业内部网络安全?好的方式是什么?

据统计,70%的数据泄露安全事故来源于企业内部。所以有效保障企业内部网络安全至关重要。但不少企业还不知道如何有效保障企业内部网络安全?也不知道有哪些好的方式?这里我们小编就跟大家来一起简单探讨一下。 什么是网络安全? 网…

【沁恒蓝牙mesh】CH58x系统时钟配置与计算

本文主要记录了【沁恒蓝牙mesh】CH58x系统时钟配置与计算 💖 作者简介:大家好,我是喜欢记录零碎知识点的小菜鸟。😎📝 个人主页:欢迎访问我的 Ethernet_Comm 博客主页🔥🎉 支持我&am…

Redis秒杀:一人一单问题及初步解决

优惠券秒杀一人一单 前言一、需求以及之前存在的问题二、增加一人一单逻辑1.初步代码2.封装一人一单逻辑3.控制锁的粒度 三、事务控制问题四、总结 前言 跟随黑马虎哥学习redis: 这是我认为b站上最好的redis教程,各方面讲解透彻,知识点覆盖…

【网络安全带你练爬虫-100练】第16练:使用session发送请求

目录 一、目标1:使用seesion进去请求 二、网络安全O 一、目标1:使用seesion进去请求 (1)应用: 通过创建会话(session)对象来请求并爬取返回的数据包 情景:需要登录才能爬取的网…

六、JVM-垃圾收集器浅析

垃圾收集器浅析 主 JVM参数 3.1.1 标准参数 -version -help -server -cp3.1.2 -X参数 非标准参数,也就是在JDK各个版本中可能会变动 -Xint 解释执行 -Xcomp 第一次使用就编译成本地代码 -Xmixed 混合模式,JVM自己来决定3.1.3 -XX参数 使用得…

四、JVM-对象内存模型

Java对象内存模型 一个Java对象在内存中包括3个部分:对象头、实例数据和对齐填充 数据 内存 – CPU 寄存器 -127 补码 10000001 - 11111111 32位的处理器 一次能够去处理32个二进制位 4字节的数据 64位操作系统 8字节 2的64次方的寻址空间 指针压缩技术 JDK1.6出…

elb 直接配置到后端服务器组

出现上图报错的原因是,前面elb配置了https证书,后端的nginx也配置了证书,导致冲突。 需要修改后端的nginx配置文件,将证书配置注释掉。 如果出现健康检查异常,需要在对应服务器的安全组上配置elb所在的网段的访问权限…

以CS32F031为例浅说国产32位MCU的内核处理器

芯片内核又称CPU内核,它是CPU中间的核心芯片,是CPU最重要的组成部分。由单晶硅制成,CPU所有的计算、接受/存储命令、处理数据都由核心执行。各种CPU核心都具有固定的逻辑结构,一级缓存、二级缓存、执行单元、指令级单元和总线接口…

PHP使用Redis实战实录3:数据类型比较、大小限制和性能扩展

PHP使用Redis实战实录系列 PHP使用Redis实战实录1:宝塔环境搭建、6379端口配置、Redis服务启动失败解决方案PHP使用Redis实战实录2:Redis扩展方法和PHP连接Redis的多种方案PHP使用Redis实战实录3:数据类型比较、大小限制和性能扩展 数据类型…

节日福利发什么?OI易问卷调查员工意见,“卷”赢其他公司

春节、妇女节、端午节、中秋节、元宵节、周年庆……近几年各公司之间的员工福利比拼“卷”上新高度,让HR、行政每逢佳节倍焦虑。 节日福利是表达公司对员工的关心和感谢,同时提高员工的归属感和满意度。礼品、购物券、节日慰问金、节日活动、食品饮料……

【雕爷学编程】MicroPython动手做(27)——物联网之掌控板小程序

知识点:什么是掌控板? 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片,支持WiFi和蓝牙双模通信,可作为物联网节点,实现物联网应用。同时掌控板上集成了OLED…

[Linux]手把手教你制作进度条小程序

[Linux]制作进度条小程序 文章目录 [Linux]制作进度条小程序C语言中的\n和\r字符缓冲区的刷新策略进行进度条代码编写 C语言中的\n和\r字符 C语言中字符分为两种: 可显字符控制字符 其中可显字符就是字符a这类的字符,控制字符就是\n这种控制字符。 对于我们制作…

便捷就医新选择,深度解析诊所小程序的功能要求

随着移动互联网的快速发展,越来越多的诊所选择开发诊所小程序来提供便捷的医疗服务。诊所小程序是一种基于微信平台的轻量级应用程序,为用户提供在线挂号、诊疗记录查看、医生咨询等功能。本文将介绍诊所小程序的功能要求,以帮助诊所更好地了…

web集群学习--静态网页和动态网页的区别、WEB1.0和WEB2.0的区别、Tomcat安装以及部署jpress应用

1.静态网页和动态网页的区别 1.1概念 静态网页: 由在服务器上提前创建好的HTML文件组成,它的内容在用户请求页面时不会发生改变。当用户访问一个静态网页时,服务器会直接将预先准备好的HTML文件发送给用户的浏览器进行显示。因为静态网页的…