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 最强大的功能之一,是访问集合元素的一种…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
