多态:解锁面向对象编程的无限可能

1. 概述

多态(Polymorphism)是面向对象编程的三大核心特性之一(另两个是封装和继承)。多态意味着不同的对象对同一消息做出不同的响应。简单来说,多态允许你使用父类引用指向子类对象,并且当调用方法时,实际执行的是子类覆盖或继承的方法。

在这里插入图片描述


2. 用途

多态的主要用途在于提高代码的灵活性和可重用性。它允许我们编写更通用的代码,这些代码可以在不修改的情况下与多种不同类型的对象一起工作。这极大地降低了代码的耦合度,使得系统更加易于维护和扩展。


3. 关键点

  • 方法重写:子类必须提供父类中声明的方法的实现,这通常是通过重写(Override)来实现的。
  • 向上转型:父类引用可以指向子类对象,这被称为向上转型(Upcasting)。
  • 运行时绑定:多态的实现依赖于运行时绑定(Runtime Binding),即在运行时确定要调用的方法。

4. 代码示例

4.1 示例1(形状绘制)

在这个例子中,有一个Shape接口和一些实现该接口的类(如Circle、Rectangle),每个类都有一个draw方法。

// 接口 Shape  
public interface Shape {  
    void draw();  
}  
  
// 实现类 Circle  
public class Circle implements Shape {  
    @Override  
    public void draw() {  
        System.out.println("Drawing a circle.");  
    }  
}  
  
// 实现类 Rectangle  
public class Rectangle implements Shape {  
    @Override  
    public void draw() {  
        System.out.println("Drawing a rectangle.");  
    }  
}  
  
// 主程序  
public class Main {  
    public static void main(String[] args) {  
        Shape[] shapes = {new Circle(), new Rectangle()}; // 使用 Shape 类型的数组来保存不同形状的对象  
          
        for (Shape shape : shapes) {  
            shape.draw(); // 调用各自实现类的 draw 方法,展示了多态性  
        }  
    }  
}
  • 在上面的例子中,我们使用了接口而不是抽象类来定义Shape,但多态的概念是相同的。我们通过将不同形状的对象放入Shape类型的数组并使用draw方法,展示了多态的效果。程序在运行时确定了实际调用哪个类的draw方法,这就是动态绑定(或晚期绑定)的例子。

4.2 示例2(计算器)

下面是一个更具体的多态例子,涉及到一个简单的计算器程序,其中有一个Operation接口以及它的几个实现类(如AdditionSubtraction等),这些类表示不同的数学运算。

// 定义一个操作接口  
public interface Operation {  
    double apply(double a, double b);  
}  
  
// 加法实现类  
public class Addition implements Operation {  
    @Override  
    public double apply(double a, double b) {  
        return a + b;  
    }  
}  
  
// 减法实现类  
public class Subtraction implements Operation {  
    @Override  
    public double apply(double a, double b) {  
        return a - b;  
    }  
}  
  
// 乘法实现类  
public class Multiplication implements Operation {  
    @Override  
    public double apply(double a, double b) {  
        return a * b;  
    }  
}  
  
// 除法实现类(注意这里我们需要处理除数为0的情况)  
public class Division implements Operation {  
    @Override  
    public double apply(double a, double b) {  
        if (b == 0) {  
            throw new IllegalArgumentException("Cannot divide by zero.");  
        }  
        return a / b;  
    }  
}  
  
// 主程序  
public class Main {  
    public static void main(String[] args) {  
        // 创建一个Operation类型的数组,用于存储不同的操作对象  
        Operation[] operations = {new Addition(), new Subtraction(), new Multiplication(), new Division()};  
  
        // 示例数据  
        double operand1 = 10;  
        double operand2 = 2;  
  
        // 遍历数组并应用每种操作  
        for (Operation operation : operations) {  
            try {  
                double result = operation.apply(operand1, operand2);  
                System.out.println("Operation result: " + result);  
            } catch (IllegalArgumentException e) {  
                System.out.println("Error: " + e.getMessage());  
            }  
        }  
    }  
}
  • 在这个例子中,定义了一个Operation接口,它有一个apply方法用于执行某种操作。然后,我们为加法、减法、乘法和除法分别创建了实现这个接口的类。在Main类的main方法中,我们创建了一个Operation类型的数组,并将这些实现类的实例添加到数组中。当我们遍历这个数组并调用每个对象的apply方法时,就展示了多态的效果:程序在运行时确定了应该调用哪个类的apply方法,并返回相应的结果。
  • 这个例子还展示了多态的一个好处,即我们可以编写通用的代码来处理不同类型的操作,而不需要为每个操作编写特定的代码。这提高了代码的复用性和可维护性。

5. 优缺点

5.1 优点
  • 提高代码的可读性和可维护性。
  • 简化复杂系统的设计。
  • 使得系统更加灵活和可扩展。
5.2 缺点
  • 如果过度使用多态,可能会导致系统变得难以理解和维护。
  • 在某些情况下,可能会降低性能(由于运行时绑定和可能的虚函数表查找)。

6. 注意事项

  • 方法签名:当重写父类方法时,必须保持相同的方法签名(方法名和参数列表)。
  • 访问修饰符:子类重写的方法的访问修饰符不能比父类方法更严格。
  • 异常:子类重写的方法抛出的异常类型必须是父类方法抛出异常类型的子集或相同类型。
  • 在使用多态时,需要确保被调用的函数是虚函数,并且派生类对基类的虚函数进行了正确的重写。
  • 需要避免在父类中声明非虚函数并在子类中重写它,因为这可能会导致不可预期的行为。
  • 在设计类时,需要仔细考虑哪些方法应该声明为虚函数,以确保多态的正确使用。

7. 多态和继承的区别与联系

7.1 区别
  1. 概念定义
    • 继承:继承是面向对象编程的一个重要特性,它允许一个类(子类或派生类)继承另一个类(父类或基类)的属性和方法。这样,子类就具有了父类的所有特性,同时还可以添加自己的新特性。
    • 多态:多态是面向对象编程中的另一个核心概念,它指的是同一种事物表现出的多种形态。在编程中,多态通常通过方法重写(Override)和向上转型(Upcasting)来实现。当使用父类引用指向子类对象时,如果子类重写了父类的方法,那么调用该方法时就会执行子类的方法,而不是父类的方法。
  2. 关注点
    • 继承主要关注的是代码的重用和扩展,通过继承,子类可以获取父类的属性和方法,并可以添加或覆盖自己的成员。
    • 多态主要关注的是接口的统一性和行为的多样性,它允许我们以统一的方式处理不同类型的对象,并在运行时确定实际执行的方法。
  3. 实现方式
    • 继承是通过类之间的层次关系来实现的,子类继承父类,从而获取父类的特性。
    • 多态是通过方法重写和向上转型来实现的,子类重写父类的方法,并通过父类引用指向子类对象来调用该方法。
7.2 联系
  1. 多态建立在继承的基础上:多态通常是通过继承来实现的,子类继承父类并重写父类的方法,从而表现出不同的行为。没有继承,就无法实现多态。
  2. 共同促进面向对象编程:继承和多态都是面向对象编程的重要特性,它们共同促进了代码的重用性、可扩展性和可维护性。通过继承,我们可以实现代码的重用和扩展;通过多态,我们可以实现接口的统一和行为的多样性。
  3. 提高代码的可读性和可维护性:通过继承和多态,我们可以将代码组织成更加清晰和易于理解的结构。子类可以继承父类的属性和方法,从而避免了大量的重复代码;同时,多态允许我们以统一的方式处理不同类型的对象,使得代码更加简洁和易于维护。

综上所述,多态和继承在面向对象编程中扮演着不同的角色,但它们之间存在着密切的联系。通过合理地使用继承和多态,我们可以编写出更加灵活、可扩展和可维护的代码。


8. 多态与多态性的区别

在面向对象编程中,多态(Polymorphism)和多态性(Polymorphism Property)常常被提及,它们虽然紧密相关,但在概念上存在一些微妙的区别。

  1. 概念定义

    • 多态:在编程中,多态指的是允许不同的类对象对同一消息做出响应。具体实现上,多态通常包括两种形式:重载(Overloading)和重写(Overriding)。重载是指同一作用域内可以有多个名称相同但参数列表不同的方法。重写则是指子类可以提供一个与父类方法签名相同但实现不同的方法。多态的核心是,当我们用父类类型的引用指向子类对象时,实际执行的是子类重写或重载后的方法。
    • 多态性:多态性则是指在不考虑实例类型的情况下使用实例的能力。它描述的是一种“一种接口,多种实现”的编程思想。多态性强调的是一种特性或能力,即允许我们在不知道对象具体类型的情况下,以统一的方式调用对象的方法。
  2. 侧重点

    • 多态:更侧重于实现方式和机制,即如何通过重载和重写等技术手段来实现不同的类对象对同一消息的响应。
    • 多态性:更侧重于描述对象之间的一种关系或特性,即如何在不关注对象具体类型的情况下,以统一的方式使用这些对象。
  3. 应用场景

    • 多态:在编程中,我们常常使用多态来实现接口的统一和代码的复用。例如,我们可以定义一个动物类(Animal),然后让狗类(Dog)和猫类(Cat)都继承自动物类,并分别实现各自的叫声方法(sound())。这样,当我们有一个动物数组时,就可以循环遍历数组,并调用每个动物的叫声方法,而无需关心具体是哪种动物。这就是多态的一个典型应用场景。
    • 多态性:多态性则更多地体现在设计模式和框架中。例如,在Java的集合框架中,我们可以使用List接口来引用ArrayList、LinkedList等不同类型的列表对象,并调用它们的统一接口方法(如add()、get()等)。这就是多态性的一个典型应用场景。
  4. 总结

    • 多态和多态性都是面向对象编程中的重要概念,它们相互关联但又有所不同。多态强调的是实现方式和机制,而多态性则强调的是对象之间的一种关系或特性。在编程中,我们需要根据具体的应用场景和需求来选择合适的概念和技术手段来实现我们的目标。

9. 多态的深入讨论

  1. 深层含义
    • 多态不仅体现在子类重写父类的方法上,更体现在它使得我们能够以统一的接口来处理不同的对象。这种统一的接口降低了代码之间的耦合度,提高了系统的可扩展性和可维护性。
    • 多态使得我们可以将关注点从具体的实现细节上转移到更高层次的抽象概念上,从而更容易理解和组织代码。
  2. 实现方式
    • 在C++中,多态主要通过虚函数和基类的指针或引用来实现。子类需要重写基类的虚函数,然后通过基类的指针或引用来调用这些函数,以实现多态的效果。
    • 在Java中,多态的实现则依赖于继承、重写和向上转型。子类需要继承父类并重写父类的方法,然后父类的引用可以指向子类的对象,从而实现多态。
  3. 多态与设计模式
    • 多态是许多设计模式(如策略模式、模板方法模式、观察者模式等)的基础。通过多态,这些设计模式能够实现更灵活和可扩展的系统架构。
  4. 多态的深入应用
    • 在大型项目中,多态常常被用于实现各种复杂的业务逻辑和交互场景。例如,在游戏开发中,多态可以用于实现不同角色的不同行为;在电商系统中,多态可以用于实现不同商品的不同定价策略等。
  5. 多态与接口
    • 在某些情况下,可以使用接口来替代基类来实现多态。接口定义了一组方法的规范,任何实现该接口的类都必须提供这些方法的实现。通过接口引用,我们可以调用不同实现类的方法,从而实现多态的效果。这种方式更加灵活和可扩展,因为实现类之间不需要有直接的继承关系。

10. 总结

多态是面向对象编程中一项强大的特性,它允许我们使用统一的接口来处理多种不同类型的对象。通过多态,我们可以编写更加灵活、可扩展和可维护的代码。然而,在使用多态时,我们也需要注意一些关键点和注意事项,以确保代码的正确性和性能。

在这里插入图片描述


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

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

相关文章

设计模式分享

2. 策略模式 2.1 定义:策略模式定义了家族算法,分别封装起来(这些算法完成的都是相同的工作,只是实现不同),它可以用相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。此模式…

huggingface笔记:使用accelerate加速

1 介绍 随着模型规模的增大,并行处理已成为在有限硬件上训练大型模型和提高训练速度的重要策略。Hugging Face 创建了Accelerate库,帮助用户在任何类型的分布式环境中轻松训练Transformers模型,无论是单机多GPU还是跨多机的多GPU 2 创建Acce…

微信公众号自定义分销商城小程序源码系统 带完整的安装代码吧以及系统部署搭建教程

系统概述 微信公众号自定义分销商城小程序源码系统是一款功能强大的电商解决方案,它集成了商品管理、订单处理、支付接口、分销管理等多种功能。该系统支持自定义界面设计,商家可根据自身需求调整商城的页面布局和风格,打造独特的品牌形象。…

多客开源】游戏陪玩系统,游戏陪玩源码,游戏陪玩语音社交源码运营版游戏陪玩平台源码/tt语音聊天/声优服务/陪玩系统源码开黑/约玩源码

介绍 我们针对陪玩app源码市场的发展趋势,整合市面上主流陪玩app应用功能,自主开发了多客陪玩系统源码,并可为客户提供全部原生陪玩源码,进行二次开发,打造适用于线上游戏陪玩、语音聊天、心理咨询、情感陪伴等业务场…

玩转Matlab-Simscape(初级)- 08 - 基于Solidworks、Matlab Simulink、COMSOL的协同仿真(案例实战)

** 玩转Matlab-Simscape(初级)- 08 - 基于Solidworks、Matlab Simulink、COMSOL的协同仿真(案例实战) ** 目录 玩转Matlab-Simscape(初级)- 08 - 基于Solidworks、Matlab Simulink、COMSOL的协同仿真&…

RockTree Capital石木资本品牌升级 沉浸式“加密朋克风”网站震撼上线

总部位于北京的领先的Web3 原生加密基金与投资机构 RockTree Capital 石木资本,宣布推出全新沉浸式网站,在其中呈现一个未来主义电影风格概念:赛博朋克加密城市。这个前沿互动型城市景观代表着 RockTree Capital 对 Web3 普及以及技术、金融与…

AI预测体彩排3采取878定位大底=23策略+杀断组+杀组选+杀和尾+杀和值012缩水测试5月16日预测第2弹

昨天的87823大底测试第一次测试,已经成功命中! 今天继续测试,仍旧目标为:10期中至少5中期。好了,废话不多说了,直接上结果吧~ 首先,878定位如下: 百位:4,5,6,3,8,1,9,0…

【Unity Shader入门精要 第7章】基础纹理(三)

1. 渐变纹理 另外一种对于纹理的使用方式是通过渐变纹理为物体提供漫反射光照效果。 顾名思义,渐变纹理本身就是一张颜色渐变(可以是连续渐变,也可能是突变)的图片,这个渐变的过程模拟的就是光源从不同的角度照射物体…

Python代码:七、小数化整数

1、题目 日常生活中我们会遇到很多小数,但是有的人不喜欢小数,因此会用四舍五入的方式将其去掉。在Python中我们更加简单,可以利用强制类型转换将小数转变成整数,请你试一试。 2、代码 import sysn float(input()) print(int(…

JUnit5超时处理

测试过程中如果某条测试用例执行过程中阻塞,就会发生超时问题: 阻塞其他用例的执行对于某些用例,如果用例执行时间过长,那么本身就是bug 使用场景: 使用JUnit5自带的超时处理,当测试用例执行时间超过执行…

mybatis-plus-ui代码生成器

mybatis-plus-generator-ui 提供交互式的Web UI用于生成兼容mybatis-plus框架的相关功能代码,包括Entity,Mapper,Mapper.xml,Service,Controller等 ,可以自定义模板以及各类输出参数,也可通过SQL查询语句直接生成代码。 使用方法 引入mave…

邮箱API发信有哪些限制?如何设置API接口?

腾讯云邮箱API与AokSend相比,有哪些优势和特性差异? 使用邮箱API发信并非毫无限制,如何正确设置API接口并选择合适的服务商,成为企业关注的焦点。接下来,Aok将探讨邮箱API发信的限制、API接口的设置方法,以…

图文并茂:解析Spring Boot Controller返回图片的三种方式

欢迎来到我的博客,代码的世界里,每一行都是一个故事 图文并茂:解析Spring Boot Controller返回图片的三种方式 前言使用Base64编码返回图片使用byte数组返回图片使用Resource对象返回图片图片格式转换与性能对比 前言 在互联网的世界里&…

LiveGBS流媒体平台GB/T28181用户手册-国标设备:设备列表、通道列表、流传输模式修改、查看通道播放、设备录像、在线状态、流量统计

LiveGBS流媒体平台GB/T28181用户手册-国标设备:设备列表、通道列表、流传输模式修改、查看通道播放、设备录像、在线状态、流量统计 1、国标设备1.1、设备列表1.1.1、查看通道1.1.2、更新通道1.1.3、编辑1.1.3、导入导出1.1.4、条件检索1.1.5、设备状态记录1.1.6、设备流量统计…

太平洋产险海南分公司提醒您:高温来袭!新能源车该如何正确充电?

据不完全统计 近三年来 7-8月一直是电动汽车烧车事故的高发期 毕竟夏季的高温影响着动力电池的状态新能源汽车为什么会自燃? 小保替你们找到了央视的官方回答! 原来 新能源汽车比传统燃油车多了一套电池系统 电解液为可燃物 当热量聚集达到燃点却没…

【错题集-编程题】主持人调度(二)(贪心 + 优先级队列)

牛客对应题目链接:主持人调度(二)_牛客题霸_牛客网 (nowcoder.com) 一、分析题目 把区间按照左端点排序,然后搞个堆: 先把第⼀个区间的右端点加⼊到堆中。遍历后⾯的区间,分情况讨论:&#xff…

双向链表结构

1.双向链表定义 双向链表也叫双链表&#xff0c;是链表的一种&#xff0c;它的每个数据节点中都有两个指针&#xff0c;分别指向直接前驱和直接后继。 2.实现双向链表 2.1创建双向链表类 /*** 基于双向链表实现元素存取的容器* param <E>*/ public class MyDoubleLinked…

设计模式六大原则之依赖倒置原则

文章目录 概念逻辑关系 小结 概念 依赖倒置原则指在设计代码架构时&#xff0c;高层模块不应该依赖底层模块&#xff0c;二者都应该依赖抽象。抽象不应该依赖于细节&#xff0c;细节应该依赖于抽象。 逻辑关系 如上图所示&#xff0c;逻辑应该就是这样&#xff0c;高层依赖于…

企业微信网页应用开发(java版)

1、成为开发者 企业微信先认证企业,成为开发者,到开发者中心创建web应用 开发者中心 选择工具 2、创建一个web应用 填写web应用信息 填写配置开发信息 域名地址先填一样的,填好后创建应用 3、配置可信域名 点击检查可信域名归属 下载可信域名验证文件 将下好的文件放到…

[案例分享] 产品需求跨职能团队协作

跨职能团队协作不仅可以激发创新、提升生产力&#xff0c;还能促进业务目标的达成。