当前位置: 首页 > news >正文

C#入门(9):多态介绍与代码演示

多态性是面向对象编程的一个核心概念,它允许你使用一个父类引用来指向一个子类对象。这可以使程序具有可扩展性,并且可以用来实现一些高级编程技术,如接口、事件、抽象类等。

多态相关的概念

以下是一些在C#中使用多态性的关键概念:

虚方法 (Virtual Methods)

在C#中,一个类可以声明一个或多个虚方法。一个虚方法有一个基础实现,可以在派生类中被覆写。为了覆写一个方法,派生类必须声明该方法,并使用override关键字。然后,当通过基类引用调用一个虚方法时,会根据引用的实际类型来调用正确的方法实现。

抽象方法 (Abstract Methods)

一个抽象方法是一个没有实现的方法,它在抽象类中声明,并且必须在任何非抽象的派生类中实现。当通过基类引用调用一个抽象方法时,会根据引用的实际类型来调用正确的方法实现。

接口 (Interfaces)

在C#中,一个接口可以被任何类实现,接口定义了一组方法和属性,但是没有提供实现。当一个类实现了一个接口,它保证了该类提供了接口定义的所有方法和属性。这意味着你可以通过接口引用来调用这些方法和属性,而不用关心对象的实际类型。

基类引用派生类对象

多态性的一个关键特性是,你可以使用基类的引用或接口的引用来引用派生类的对象。当你通过这样的引用调用一个方法时,CLR会根据实际的对象类型来确定应该调用哪个方法。这使得你可以写出更具有通用性的代码,这些代码可以处理任何派生自特定基类或实现特定接口的对象。

例如,如果你有一个Animal类和一些派生自Animal的类,如DogCat,你可以写一个方法,该方法接收一个Animal引用,并通过这个引用调用MakeSound方法。不论传入的实际对象是Dog还是Cat,都可以正确地调用对应的MakeSound方法。这样,你就不需要为DogCat分别写两个方法。

多态性是一个强大的工具,它可以使你的代码更加灵活和可扩展。通过理解和正确使用多态性,你可以提高你的代码质量,并写出更具有可维护性和可扩展性的代码。

在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方法,分别接收一个intdoublestring类型的参数。编译器会根据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会根据实际的对象类型来调用正确的方法实现。这就是多态的作用,使得我们可以写出更通用的代码,而不需要知道或检查对象的具体类型。

http://www.lryc.cn/news/235765.html

相关文章:

  • 可拖动、可靠边的 popupWindow 实现
  • C# 依赖注入如何实现
  • Redis 9 数据库
  • 43-设计问题-最小栈
  • 基于RK3588全高端智能终端机器人主板
  • 穿越风波,“长红”的直播电商依然扎根产业和消费者
  • LLM大模型 (chatgpt) 在搜索和推荐上的应用
  • 中国净初级生产力年度合成产品NPP(MYD17A3H.006)
  • GitHub如何删除仓库
  • 漫谈广告机制设计 | 万剑归宗:聊聊广告机制设计与收入提升的秘密(3)
  • 安装系统时无raid驱动处理办法
  • ForkLift:macOS文件管理器/FTP客户端
  • 信息系统项目管理师 第四版 第20章 高级项目管理
  • Apache Pulsar 技术系列 - 基于 Pulsar 的海量 DB 数据采集和分拣
  • HDFS、MapReduce原理--学习笔记
  • PC端使子组件的弹框关闭
  • PHPStorm PHP-CS-Fixer
  • SpringBoot中日志的使用log4j
  • 迭代器与生成器
  • 适用于 Windows 的 10 个最佳视频转换器:快速转换高清视频
  • 分布式锁的概念、应用场景、实现方式和优缺点对比
  • Linux:常见指令
  • 大数据基础设施搭建 - ZooKeeper
  • 网站优化工具Google Optimize
  • PostgreSQL创建分区表,并插入大量数据
  • NewStarCTF2023 Reverse Week3 EzDLL WP
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • php-cli
  • [C/C++] 数据结构 LeetCode:用队列实现栈
  • ESP32网络开发实例-物联网声污染监测系统