多态:解锁面向对象编程的无限可能
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
接口以及它的几个实现类(如Addition
、Subtraction
等),这些类表示不同的数学运算。
// 定义一个操作接口
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 区别
- 概念定义
- 继承:继承是面向对象编程的一个重要特性,它允许一个类(子类或派生类)继承另一个类(父类或基类)的属性和方法。这样,子类就具有了父类的所有特性,同时还可以添加自己的新特性。
- 多态:多态是面向对象编程中的另一个核心概念,它指的是同一种事物表现出的多种形态。在编程中,多态通常通过方法重写(Override)和向上转型(Upcasting)来实现。当使用父类引用指向子类对象时,如果子类重写了父类的方法,那么调用该方法时就会执行子类的方法,而不是父类的方法。
- 关注点
- 继承主要关注的是代码的重用和扩展,通过继承,子类可以获取父类的属性和方法,并可以添加或覆盖自己的成员。
- 多态主要关注的是接口的统一性和行为的多样性,它允许我们以统一的方式处理不同类型的对象,并在运行时确定实际执行的方法。
- 实现方式
- 继承是通过类之间的层次关系来实现的,子类继承父类,从而获取父类的特性。
- 多态是通过方法重写和向上转型来实现的,子类重写父类的方法,并通过父类引用指向子类对象来调用该方法。
7.2 联系
- 多态建立在继承的基础上:多态通常是通过继承来实现的,子类继承父类并重写父类的方法,从而表现出不同的行为。没有继承,就无法实现多态。
- 共同促进面向对象编程:继承和多态都是面向对象编程的重要特性,它们共同促进了代码的重用性、可扩展性和可维护性。通过继承,我们可以实现代码的重用和扩展;通过多态,我们可以实现接口的统一和行为的多样性。
- 提高代码的可读性和可维护性:通过继承和多态,我们可以将代码组织成更加清晰和易于理解的结构。子类可以继承父类的属性和方法,从而避免了大量的重复代码;同时,多态允许我们以统一的方式处理不同类型的对象,使得代码更加简洁和易于维护。
综上所述,多态和继承在面向对象编程中扮演着不同的角色,但它们之间存在着密切的联系。通过合理地使用继承和多态,我们可以编写出更加灵活、可扩展和可维护的代码。
8. 多态与多态性的区别
在面向对象编程中,多态(Polymorphism)和多态性(Polymorphism Property)常常被提及,它们虽然紧密相关,但在概念上存在一些微妙的区别。
-
概念定义
- 多态:在编程中,多态指的是允许不同的类对象对同一消息做出响应。具体实现上,多态通常包括两种形式:重载(Overloading)和重写(Overriding)。重载是指同一作用域内可以有多个名称相同但参数列表不同的方法。重写则是指子类可以提供一个与父类方法签名相同但实现不同的方法。多态的核心是,当我们用父类类型的引用指向子类对象时,实际执行的是子类重写或重载后的方法。
- 多态性:多态性则是指在不考虑实例类型的情况下使用实例的能力。它描述的是一种“一种接口,多种实现”的编程思想。多态性强调的是一种特性或能力,即允许我们在不知道对象具体类型的情况下,以统一的方式调用对象的方法。
-
侧重点
- 多态:更侧重于实现方式和机制,即如何通过重载和重写等技术手段来实现不同的类对象对同一消息的响应。
- 多态性:更侧重于描述对象之间的一种关系或特性,即如何在不关注对象具体类型的情况下,以统一的方式使用这些对象。
-
应用场景
- 多态:在编程中,我们常常使用多态来实现接口的统一和代码的复用。例如,我们可以定义一个动物类(Animal),然后让狗类(Dog)和猫类(Cat)都继承自动物类,并分别实现各自的叫声方法(sound())。这样,当我们有一个动物数组时,就可以循环遍历数组,并调用每个动物的叫声方法,而无需关心具体是哪种动物。这就是多态的一个典型应用场景。
- 多态性:多态性则更多地体现在设计模式和框架中。例如,在Java的集合框架中,我们可以使用List接口来引用ArrayList、LinkedList等不同类型的列表对象,并调用它们的统一接口方法(如add()、get()等)。这就是多态性的一个典型应用场景。
-
总结
- 多态和多态性都是面向对象编程中的重要概念,它们相互关联但又有所不同。多态强调的是实现方式和机制,而多态性则强调的是对象之间的一种关系或特性。在编程中,我们需要根据具体的应用场景和需求来选择合适的概念和技术手段来实现我们的目标。
9. 多态的深入讨论
- 深层含义
- 多态不仅体现在子类重写父类的方法上,更体现在它使得我们能够以统一的接口来处理不同的对象。这种统一的接口降低了代码之间的耦合度,提高了系统的可扩展性和可维护性。
- 多态使得我们可以将关注点从具体的实现细节上转移到更高层次的抽象概念上,从而更容易理解和组织代码。
- 实现方式
- 在C++中,多态主要通过虚函数和基类的指针或引用来实现。子类需要重写基类的虚函数,然后通过基类的指针或引用来调用这些函数,以实现多态的效果。
- 在Java中,多态的实现则依赖于继承、重写和向上转型。子类需要继承父类并重写父类的方法,然后父类的引用可以指向子类的对象,从而实现多态。
- 多态与设计模式
- 多态是许多设计模式(如策略模式、模板方法模式、观察者模式等)的基础。通过多态,这些设计模式能够实现更灵活和可扩展的系统架构。
- 多态的深入应用
- 在大型项目中,多态常常被用于实现各种复杂的业务逻辑和交互场景。例如,在游戏开发中,多态可以用于实现不同角色的不同行为;在电商系统中,多态可以用于实现不同商品的不同定价策略等。
- 多态与接口
- 在某些情况下,可以使用接口来替代基类来实现多态。接口定义了一组方法的规范,任何实现该接口的类都必须提供这些方法的实现。通过接口引用,我们可以调用不同实现类的方法,从而实现多态的效果。这种方式更加灵活和可扩展,因为实现类之间不需要有直接的继承关系。
10. 总结
多态是面向对象编程中一项强大的特性,它允许我们使用统一的接口来处理多种不同类型的对象。通过多态,我们可以编写更加灵活、可扩展和可维护的代码。然而,在使用多态时,我们也需要注意一些关键点和注意事项,以确保代码的正确性和性能。
相关文章:

多态:解锁面向对象编程的无限可能
1. 概述 多态(Polymorphism)是面向对象编程的三大核心特性之一(另两个是封装和继承)。多态意味着不同的对象对同一消息做出不同的响应。简单来说,多态允许你使用父类引用指向子类对象,并且当调用方法时&am…...

学习MySQL(四):记录的增删改查
记录的增、删、改 增 -- 插入一条数据 INSERT INTO 表名(字段 1,字段2,字段3) VALUES(值 1,值2,值3) INSERT INTO 表名 VALUES(值 1,值2,值3&am…...

如何使用Python进行网页爬取
Python爬虫案例可以有很多种,但我会为你提供一个简单的案例,该案例使用Python的requests库来爬取一个网页的内容,并使用BeautifulSoup库来解析HTML并提取特定的信息。 假设我们要从某个新闻网站(例如:示例网站&#x…...

Spring的IOC(Inversion of Control)设计模式
Spring的IOC(Inversion of Control)是一种设计模式,它通过控制反转的思想来降低组件之间的耦合度。在Spring框架中,IOC容器负责管理应用程序中的对象,使得对象之间的依赖关系由容器来维护和注入。 以下是Spring IOC的…...

深度学习知识点总结
深度学习是机器学习领域中的一个重要研究方向,它致力于模拟人脑的学习过程,使机器能够像人一样具有分析学习能力,识别文字、图像和声音等数据。以下是深度学习的一些关键知识点总结: 定义与目标: 深度学习是学习样本数…...

以色列人Andi Gutmans开发的php zend
虽然目前php语言不行了【相关的文章前几年已经有人发过】,但这不是重点,重点是zend引擎的东西具有极大的技术价值,负责zend引擎实现的大佬都现在差不多都是40,50岁左右了,从1997,1998,2000到202…...

Python筑基之旅-溯源及发展
目录 一、Python的起源 二、Python的版本更替及变化 三、Python的优缺点 四、Python的发展方向 五、Python之禅 六、推荐专栏/主页: 1、Python函数之旅:Functions 2、Python算法之旅:Algorithms 3、个人主页:https://mye…...

网页打开:为什么国内用新标签页,国外用当前页?
想写这个话题很久了,因为用百度和Google搜索时,打开搜索结果链接时的交互差异,几乎每天都要提醍我一下。 网页打开——这个交互,在设计里,算是极微小,但影响极广泛的操作设计。甚至,因此形成了…...

用户运营4大核心(C端版)
1、用户运营是什么 产品好比歌手,运营好比经纪公司,运营就是让一个有潜质的产品,从“草根”发展成“明星”!C端用户的产品忠诚度不高,用户运营更要维护好“粉丝”关系,从“单向的吸引”发展成“双向的进步…...

SBM模型、超效率SBM模型代码及案例数据(补充操作视频)
01、数据简介 SBM(Slack-Based Measure)模型是一种数据包络分析(Data Envelopment Analysis, DEA)的方法,用于评估决策单元(Decision Making Units, DMUs)的效率。而超效率SBM模型是对SBM模型的…...

C#知识|上位机子窗体嵌入主窗体方法(实例)
哈喽,你好啊,我是雷工! 上位机开发中,经常会需要将子窗体嵌入到主窗体, 本节练习C#中在主窗体的某个容器中打开子窗体的方法。 01 需求说明 本节练习将【账号管理】子窗体在主窗体的panelMain容器中打开。 账号管理子窗体如下: 主窗体的panelMain容器位置如图: 02 实现…...

【汇编】算术指令
一、加法指令 (一)各加法指令的格式及操作 加法指令可做字或字节运算 (1)加法指令 ADD 格式:ADD DST,SRC执行的操作:(DST) ← (SRC)(DST) (2)带进位加法指令 ADC 格式…...

如何知晓自己手机使用状况-入网时长
手机入网时长查询的重要性 在当今的数字化时代,手机已经成为我们日常生活中不可或缺的一部分。从通讯、娱乐到工作,手机几乎涵盖了生活的各个方面。而在手机使用过程中,了解手机的入网时长信息显得尤为重要。本文将深入探讨手机入网时长查询…...

机器学习 - 决策树
1. 决策树基础 定义与概念 决策树是一种监督学习算法,主要用于分类和回归任务。它通过学习从数据特征到输出标签的映射规则,构建一个树形结构。在分类问题中,决策树的每个叶节点代表一个类别。 案例分析 假设我们有一个关于天气和是否进行…...

【scikit-learn007】主成分分析(Principal Component Analysis, PCA)ML模型实战及经验总结(更新中)
1.一直以来想写下基于scikit-learn训练AI算法的系列文章,作为较火的机器学习框架,也是日常项目开发中常用的一款工具,最近刚好挤时间梳理、总结下这块儿的知识体系。 2.熟悉、梳理、总结下scikit-learn框架主成分分析(Principal C…...

还在花钱订购SSL证书吗?out啦!
SSL(Secure Sockets Layer)证书,以及其后续版本TLS(Transport Layer Security)证书,扮演了保护用户数据免遭窃听和篡改的核心角色。这些证书能够确保数据在客户端与服务器之间传输时的加密性与完整性&#…...

【GoLang基础】函数体的注意事项和细节讨论
在 Go 语言(Golang)中,函数是程序的基本构建块之一。理解函数的定义和使用是掌握 Go 语言的重要步骤。下面是关于 Go 语言中函数体的详细解释,包括函数的定义、参数传递、返回值以及闭包等方面。 1. 函数的定义 在 Go 语言中&am…...

YOLOv8训练流程-原理解析[目标检测理论篇]
关于YOLOv8的主干网络在YOLOv8网络结构介绍-CSDN博客介绍了,为了更好地学习本章内容,建议先去看预测流程的原理分析YOLOv8原理解析[目标检测理论篇]-CSDN博客,再次把YOLOv8网络结构图放在这里,方便随时查看。 1.前言 YOLOv8训练…...

实战使用Java代码操作Redis
实战使用Java代码操作Redis 1. 背景说明2. 单连接方式3. 连接池方式1. 背景说明 在工作中, 如果有一批数据需要初始化, 最方便的方法是使用代码操作Redis进行初始化。 Redis提供了多种语言的API交互方式, 这里以Java代码为例进行分析。 使用Java代码操作 Redis 需要借助…...

微信小程序之九宫格抽奖
1.实现效果 2. 实现步骤 话不多说,直接上代码 /**index.wxml*/ <view class"table-list flex fcc fwrap"><block wx:for"{{tableList}}" wx:key"id"><view class"table-item btn fcc {{isTurnOver?:grayscale…...

车牌检测识别功能实现(pyqt)
在本专题前面相关博客中已经讲述了 pyqt + yolo + lprnet 实现的车牌检测识别功能。带qt界面的。 本博文将结合前面训练好的模型来实现车牌的检测与识别。并用pyqt实现界面。最终通过检测车牌检测识别功能。 1)、通过pyqt5设计界面 ui文件如下: <?xml version="1…...

工业派-配置Intel神经计算棒二代(NCS2)
最近两天在工业派ubuntu16.04上配置了Intel神经计算棒二代——Intel Neural Compute Stick,配置过程之艰辛我都不想说了,实在是太折磨人。不过历尽千辛万苦,总算让计算棒可以在工业派ubuntu16.04系统上跑了,还是蛮欣慰的。 注&…...

深度学习中常见的九种交叉验证方法汇总
目录 1. K折交叉验证(K-fold cross-validation) 2. 分层K折交叉验证(Stratified K-fold cross-validation) 3. 时间序列交叉验证(Time Series Split) 4. 留一交叉验证(Leave-One-Out Cross-…...

企业建网站流程
企业建网站是一个复杂而繁琐的过程,需要根据企业的需求和目标进行规划、设计、开发和运营。以下是企业建网站的一般流程,主要包括以下几个步骤: 第一步:需求分析 企业建网站的第一步是进行需求分析。这个过程需要与企业负责人和相…...

Laravel通过phpSpreadsheet合并excel
背景 最近有一个需求,需要将所有excel文件的sheet合并到一个文件。 目前我们处理表格使用的是xlswriter这个插件,对于数据量比较大的话非常好用。...

CTF网络安全大赛web题目:just_sqli
这道题目是bugku的web题目 题目的 描 述: KosenCTF{} 原文链接: CTF网络安全大赛web题目:just_sqli - 红客网-网络安全与渗透技术 题目Web源代码: <?php$user NULL; $is_admin 0;if (isset($_GET["source"])) {highlig…...

Java入门基础学习笔记27——生成随机数
Random的使用:生成随机数。 随机数应用: 随机点名: 年会抽奖: 猜数字游戏: 密码学。 查看API文档: package cn.ensource.random;import java.util.Random;public class RandomDemo1 {public static voi…...

EasyImage2.0 图床源码
EasyImage2.0 是一个简单图床的源码,它支持以下功能: 1. API接口 2. 登录后才能上传图片 3. 设置图片质量 4. 压缩图片大小 5. 添加文字或图片水印 6. 设定图片的宽度和高度 7. 将上传的图片转换为指定的格式 8. 限制上传图片的最小宽度和高度 …...

人工智能创新领衔,Android系统如虎添翼:2024 Google I/O 大会深度解析
人工智能创新领衔,Android系统如虎添翼:2024 Google I/O 大会深度解析 2024年5月14日举行的Google I/O大会,犹如一场精彩的科技盛宴,吸引了全球的目光。大会上,谷歌发布了一系列重磅产品和技术更新,展现了…...

下单制造fpc的工艺参数
FPC工艺简介 - 百度文库 (baidu.com) FPC工艺参数 - 豆丁网 (docin.com) FPC柔性线路板的主要参数.ppt (book118.com) 捷多邦: 华秋: 背胶: FPC板背胶是可以粘接在光滑表面的一种薄型胶带,可以在狭小以及光滑的表面上用来提供高…...