C#入门(9):多态介绍与代码演示
多态性是面向对象编程的一个核心概念,它允许你使用一个父类引用来指向一个子类对象。这可以使程序具有可扩展性,并且可以用来实现一些高级编程技术,如接口、事件、抽象类等。
多态相关的概念
以下是一些在C#中使用多态性的关键概念:
虚方法 (Virtual Methods)
在C#中,一个类可以声明一个或多个虚方法。一个虚方法有一个基础实现,可以在派生类中被覆写。为了覆写一个方法,派生类必须声明该方法,并使用override
关键字。然后,当通过基类引用调用一个虚方法时,会根据引用的实际类型来调用正确的方法实现。
抽象方法 (Abstract Methods)
一个抽象方法是一个没有实现的方法,它在抽象类中声明,并且必须在任何非抽象的派生类中实现。当通过基类引用调用一个抽象方法时,会根据引用的实际类型来调用正确的方法实现。
接口 (Interfaces)
在C#中,一个接口可以被任何类实现,接口定义了一组方法和属性,但是没有提供实现。当一个类实现了一个接口,它保证了该类提供了接口定义的所有方法和属性。这意味着你可以通过接口引用来调用这些方法和属性,而不用关心对象的实际类型。
基类引用派生类对象
多态性的一个关键特性是,你可以使用基类的引用或接口的引用来引用派生类的对象。当你通过这样的引用调用一个方法时,CLR会根据实际的对象类型来确定应该调用哪个方法。这使得你可以写出更具有通用性的代码,这些代码可以处理任何派生自特定基类或实现特定接口的对象。
例如,如果你有一个Animal
类和一些派生自Animal
的类,如Dog
和Cat
,你可以写一个方法,该方法接收一个Animal
引用,并通过这个引用调用MakeSound
方法。不论传入的实际对象是Dog
还是Cat
,都可以正确地调用对应的MakeSound
方法。这样,你就不需要为Dog
和Cat
分别写两个方法。
多态性是一个强大的工具,它可以使你的代码更加灵活和可扩展。通过理解和正确使用多态性,你可以提高你的代码质量,并写出更具有可维护性和可扩展性的代码。
在C#中,多态表现为以下两种形式:
编译时多态:这是通过方法重载和运算符重载实现的。在编译时,编译器就可以根据方法签名或运算符参数的数量和类型确定要调用的具体方法或运算符。
编译时多态,也被称为静态多态或早期绑定,是在编译时期确定被调用的方法或属性的机制。在C#中,静态多态主要通过两种方式实现:方法重载和运算符重载。
下面分别介绍这两种功能多态
编译时多态
方法重载(Method Overloading)
方法重载允许在同一类中定义多个名称相同但参数列表不同的方法。编译器根据方法被调用时提供的参数类型和数量来确定应该调用哪个方法。
public class Printer
{public void Print(int i){Console.WriteLine($"Printing int: {i}");}public void Print(double d){Console.WriteLine($"Printing double: {d}");}public void Print(string s){Console.WriteLine($"Printing string: {s}");}
}// 使用
Printer printer = new Printer();
printer.Print(10); // 输出 "Printing int: 10"
printer.Print(3.14); // 输出 "Printing double: 3.14"
printer.Print("Hello world"); // 输出 "Printing string: Hello world"
在上述例子中,Printer
类定义了三个重载的Print
方法,分别接收一个int
、double
和string
类型的参数。编译器会根据Print
方法被调用时提供的参数类型来选择正确的方法。
运算符重载(Operator Overloading)
C#也允许我们对类或结构体的运算符进行重载,这也是一种编译时多态。我们可以定义新的运算符,以便在类或结构体的对象上执行特定的操作。
public struct Point
{public int X { get; set; }public int Y { get; set; }public static Point operator +(Point a, Point b){return new Point { X = a.X + b.X, Y = a.Y + b.Y };}
}// 使用
Point p1 = new Point { X = 1, Y = 1 };
Point p2 = new Point { X = 2, Y = 2 };
Point p3 = p1 + p2; // p3.X = 3, p3.Y = 3
在上述例子中,我们为Point
结构体重载了+
运算符,使得我们可以直接将两个Point
对象相加。
注意,虽然静态多态在编译时期就确定了被调用的方法或属性,但是仍然需要我们在编写代码时遵循一些规则,例如,对于方法重载,重载的方法必须在参数类型或参数数量上有所不同;对于运算符重载,只能重载一部分预定义的运算符,不能创建新的运算符,也不能重载一些特定的运算符(比如&&
,||
等)。
运行时多态:这是通过虚方法、抽象方法和接口实现的。在运行时,CLR(公共语言运行时)根据对象的实际类型来决定要调用的具体方法。
运行时多态
以下是一个运行时多态的例子:
public class Animal
{public virtual void MakeSound(){Console.WriteLine("The animal makes sound");}
}public class Dog : Animal
{public override void MakeSound(){Console.WriteLine("The dog barks");}
}public class Cat : Animal
{public override void MakeSound(){Console.WriteLine("The cat meows");}
}// 在其他地方使用
Animal myAnimal = new Dog();
myAnimal.MakeSound(); // 输出 "The dog barks"myAnimal = new Cat();
myAnimal.MakeSound(); // 输出 "The cat meows"
在这个例子中,Animal类定义了一个虚方法MakeSound,Dog类和Cat类覆写了这个方法。在运行时,尽管myAnimal的编译时类型是Animal,但是CLR会根据其运行时类型(即实际的对象类型)来调用正确的MakeSound方法。这就是多态的作用,使得我们可以写出更通用的代码,而不需要知道或检查对象的具体类型。
多态的主要优点是促进了代码的复用和模块化,使得代码更加灵活和可扩展。通过使用多态,我们可以写出可以处理基类和派生类的通用代码,而不需要为每一个具体的类写特定的代码。
接口实现多态
在C#中,接口是一种强大的工具,用于实现多态。接口定义了一组方法和属性,但没有提供实现。任何实现了特定接口的类都保证提供接口定义的所有方法和属性。
下面是一个使用接口实现多态的例子:
public interface IAnimal
{void MakeSound();
}public class Dog : IAnimal
{public void MakeSound(){Console.WriteLine("The dog barks");}
}public class Cat : IAnimal
{public void MakeSound(){Console.WriteLine("The cat meows");}
}// 在其他地方使用
IAnimal myAnimal = new Dog();
myAnimal.MakeSound(); // 输出 "The dog barks"myAnimal = new Cat();
myAnimal.MakeSound(); // 输出 "The cat meows"
在这个例子中,IAnimal
接口定义了一个MakeSound
方法,Dog
类和Cat
类都实现了这个接口,并提供了MakeSound
方法的实现。然后,我们可以创建一个IAnimal
引用,并让它引用一个Dog
对象或一个Cat
对象。当我们通过这个引用调用MakeSound
方法时,CLR会根据实际的对象类型来调用正确的方法实现。这就是多态的作用,使得我们可以写出更通用的代码,而不需要知道或检查对象的具体类型。
相关文章:
C#入门(9):多态介绍与代码演示
多态性是面向对象编程的一个核心概念,它允许你使用一个父类引用来指向一个子类对象。这可以使程序具有可扩展性,并且可以用来实现一些高级编程技术,如接口、事件、抽象类等。 多态相关的概念 以下是一些在C#中使用多态性的关键概念…...

可拖动、可靠边的 popupWindow 实现
0 背景 开发要实现一个可以拖动的圆角小窗,要求松手时,哪边近些靠哪边。并且还规定了拖动范围。样式如下: 1 实现 首先把 PopupWindow 的布局文件 pop.xml 实现 <?xml version"1.0" encoding"utf-8"?> <R…...
C# 依赖注入如何实现
在 C# 中,依赖注入(Dependency Injection,简称 DI)是一种编程技术,用于减少代码之间的耦合。依赖注入可以通过构造函数注入、属性注入或方法注入实现。在 .NET Core 和 .NET 5 中,还提供了一个内置的依赖注…...

Redis 9 数据库
4 设置键的生存时间或过期时间 通过EXPIRE命令或者PEXPIRE命令,客户端可以以秒或者毫秒精度为数据库中的某个键设置生存时间(TimeToLive,TTL),在经过指定的秒数或者毫秒数之后,服务器就会自动删除生存时间…...
43-设计问题-最小栈
原题链接: 198. 打家劫舍 题目描述: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入&a…...

基于RK3588全高端智能终端机器人主板
一、小尺寸板型设计 该款主板为小型板,尺寸仅为125*85mm,更小更紧凑,可完美适应各类高端智能自助终端; 二、八核高端处理器 采用RK3588S八核64位处理器,8nm LP制程,主频最高达2.4GHz,搭载Andr…...

穿越风波,“长红”的直播电商依然扎根产业和消费者
当消费者将最后一个快递拿进家门,2023年的双11也就落下了帷幕。相较于往年组队、拼单的玩法,如今最受欢迎的双11 流程,或许已经变成点进自己心仪主播、店铺的直播间,翻阅最新的产品清单,从中选择购物目标,在…...

LLM大模型 (chatgpt) 在搜索和推荐上的应用
目录 1 大模型在搜索的应用1.1 召回1.1.1 倒排索引1.1.2 倒排索引存在的问题1.1.3 大模型在搜索召回的应用 (实体倒排索引) 1.2 排序1.2.1 大模型在搜索排序应用(融入LLM实体排序) 2 大模型在推荐的应用2.1 学术界关于大模型在推荐的研究2.2 …...

中国净初级生产力年度合成产品NPP(MYD17A3H.006)
中国净初级生产力年度合成产品NPP(MYD17A3H.006)由航天宏图实验室提供,根据NASA MODIS数据(MYD17A3H.006)通过航天宏图 Smoother计算得到的平滑后NPP产品,解决了影像云雾覆盖、像元异常值等问题。对处理后的…...

GitHub如何删除仓库
GitHub如何删除仓库 删除方法第一步第二步第三步 删除方法 第一步 在仓库的界面选择Settings 第二步 选择General,页面拉到最后。 第三步 删除仓库。...

漫谈广告机制设计 | 万剑归宗:聊聊广告机制设计与收入提升的秘密(3)
书接上文漫谈广告机制设计 | 万剑归宗:聊聊广告机制设计与收入提升的秘密(2),我们聊到囚徒困境是完全信息静态博弈,参与人存在占优策略,最终达到占优均衡,并且是对称占优均衡。接下来我们继续…...
安装系统时无raid驱动处理办法
场景描述 安装系统时可以进入安装界面,但是无法识别到硬盘,查看服务器硬件均无异常且从bios或者raid配置界面中能正常看到raid信息及硬盘信息,运行lspci 命令查看到服务器有raid卡,但是未加载驱动。 获取驱动程序模块 查看raid…...

ForkLift:macOS文件管理器/FTP客户端
ForkLift 是一款macOS下双窗口的文件管理器,可以代替本地的访达。ForkLift同时具备连接Ftp、SFtp、WebDav以及云服务器。 ForkLift还具备访达不具备的小功能,比如从文件夹位置打开终端,显示隐藏文件,制作替换等功能。ForkLift 是一…...
信息系统项目管理师 第四版 第20章 高级项目管理
1.项目集管理 1.1.项目集管理标准 1.2.项目集管理角色和职责 1.3.项目集管理绩效域 2.项目组合管理 2.1.项目组合管理标准 2.2.项目组合管理角色和职责 2.3.项目组合管理绩效域 3.组织级项目管理 3.1.组织级项目管理标准 3.2.业务价值与业务评估 3.3.OPM框架要素 3…...

Apache Pulsar 技术系列 - 基于 Pulsar 的海量 DB 数据采集和分拣
导语 Apache Pulsar 是一个多租户、高性能的服务间消息传输解决方案,支持多租户、低延时、读写分离、跨地域复制、快速扩容、灵活容错等特性。本文是 Pulsar 技术系列中的一篇,主要介绍 Pulsar 在海量DB Binlog 增量数据采集、分拣场景下的应用。 前言…...

HDFS、MapReduce原理--学习笔记
1.Hadoop框架 1.1框架与Hadoop架构简介 (1)广义解释 从广义上来说,随着大数据开发技术的快速发展与逐步成熟,在行业里,Hadoop可以泛指为:Hadoop生态圈。 也就是说,Hadoop指的是大数据生态圈整…...

PC端使子组件的弹框关闭
子组件 <template><el-dialog title"新增部门" :visible"showDialog" close"close"> </el-dialog> </template> <script> export default {props: {showDialog: {type: Boolean,default: false,},},data() {retu…...

PHPStorm PHP-CS-Fixer
我用的是brew安装: brew install php-cs-fixer phpstorm配置: setting搜索fixer 指定安装php-cs-fixer的目录: https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/master/doc/installation.rst 图文详解PHPStorm实现自动执行代码格式化-…...

SpringBoot中日志的使用log4j
SpringBoot中日志的使用log4j 项目中日志系统是必不可少的,目前比较流行的日志框架有 log4j、logback 等,这两个框架的作者是同一个 人,Logback 旨在作为流行的 log4j 项目的后续版本,从而恢复 log4j 离开的位置。 另外 slf4j(…...
迭代器与生成器
章节目录: 一、迭代器1.1 相关概述1.2 基本使用1.3 自定义迭代器 二、生成器2.1 相关概述2.2 基本使用2.3 三种应用场景 三、yield 和 class 定义的迭代器对比四、结束语 一、迭代器 1.1 相关概述 迭代是 Python 最强大的功能之一,是访问集合元素的一种…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...