C# 最基础知识介绍–多态

C# 最基础知识介绍--多态

在C#中,多态是面向对象编程(OOP)中的常见概念,它允许不同类型的对象对相同的消息作出响应。简单地说,多态就是对象(或方法)有不同的表现形式。

多态性有三种形式:静态,动态和协变。下面我们会一一解释。

静态多态

静态多态性是在编译时确定的,在程序执行之前,就确定了发生的方法和参数。在编程语言C#中,静态多态性可以通过函数重载和运算符重载实现。每个函数都必须有一个唯一的名字,并且参数的数量和类型必须不同,但是在编译时确定。

以函数重载为例,假设我们有以下两个函数定义,分别实现了对数值的平方和对字符串的拼接操作。

static int Square(int n)
{
    return n * n;
}

static string Concat(string s1, string s2)
{
    return s1 + s2;
}

我们可以看到,这两个函数的名称都是不同的,他们可以同时存在于同一个程序中。

同时,由于函数的参数类型和数量不同,使得函数的调用必须显式地指明参数类型,所以编译器知道调用哪个函数。

int result = Square(3);
string str = Concat("hello", "world");

动态多态

动态多态性是在程序运行时确定的,使用基类声明的指针或引用可以指向派生类的对象。这里主要涉及到继承和虚函数的使用。

例如:

class Shape
{
    public virtual double Area()
    {
        return 0;
    }
}

class Circle : Shape
{
    double radius;

    public Circle(double r)
    {
        radius = r;
    }

    public override double Area()
    {
        return 3.14 * radius * radius;
    }
}

class Rectangle : Shape
{
    double length;
    double width;

    public Rectangle(double l, double w)
    {
        length = l;
        width = w;
    }

    public override double Area()
    {
        return length * width;
    }
}

在上面的代码示例中,我们定义了一个基类 Shape 和两个继承类 CircleRectangle。同时,Shape 中定义了一个虚函数 Area(),派生类可以覆盖这个方法来实现不同的功能。重点是在声明的时候使用了关键字 virtual 和继承类中重写的关键字 override

现在,我们可以通过基类的引用调用覆盖之后的方法,这里就是通过定义 Shape 类型的变量来指向两个派生类的实例,实现了运行时的多态性。

Shape shape1 = new Circle(3);
Shape shape2 = new Rectangle(4, 5);

double area1 = shape1.Area();
double area2 = shape2.Area();

协变

协变允许派生类的方法返回基类的对象。换句话说,协变可以将派生类作为基类来使用。

例如:

interface ICovariant<out T>
{
    T Get();
}

class Animal { }
class Cat : Animal { }

class CovariantCat : ICovariant<Cat>
{
    public Cat Get()
    {
        return new Cat();
    }
}

class CovariantAnimal : ICovariant<Animal>
{
    public Animal Get()
    {
        return new Animal();
    }
}

在上面的代码示例中,我们定义了一个协变接口 ICovariant<T>,其中 out 关键字表示协变。然后定义了两个派生类 CovariantCatCovariantAnimal,显然 CovariantCat 中的 Get() 方法返回的是 Cat 类型的对象,而 CovariantAnimal 中的 Get() 方法返回的是 Animal 类型的对象,但是由于使用了协变,这个方法也可以将派生类的实例也返回给基类。

ICovariant<Animal> animal = new CovariantCat();
Animal animalObj = animal.Get();

在这个示例中,我们将 CovariantCat 类型的对象赋值给 ICovariant<Animal> 类型的变量。此时,使用 Get() 方法从接口中获取的对象仍然是 Cat 类型,但是编译器会将它转换成 Animal 对象,以允许将派生类对象作为基类来使用。

示例说明

下面举两个具体的例子来说明多态的使用方法。

示例一:吃饭

class Animal
{
    public virtual void Eat()
    {
        Console.WriteLine("动物在吃...");
    }
}

class Cat : Animal
{
    public override void Eat()
    {
        Console.WriteLine("猫在吃鱼...");
    }
}

class Dog : Animal
{
    public override void Eat()
    {
        Console.WriteLine("狗在吃肉...");
    }
}

在上面的代码中,我们定义了一个抽象的 Animal 类,然后 CatDog 类都继承自 Animal 类。同时,Animal 类中定义了一个 Eat() 方法。CatDog 类都重写了 Eat() 方法。

然后我们可以创建一个 List<Animal> 来表示动物园中的动物们,然后调用它们的 Eat() 方法。

List<Animal> animals = new List<Animal>();
animals.Add(new Cat());
animals.Add(new Dog());

foreach (Animal animal in animals)
{
    animal.Eat();
}

输出结果如下:

猫在吃鱼...
狗在吃肉...

我们可以看到,由于 CatDog 类重写了 Eat() 方法,调用 List<Animal> 类型的对象的 Eat() 方法时,会根据实际执行的对象来调用对应的方法。这种由对象的实际类型来决定方法的调用方式,就是运行时多态。

示例二:图形面积计算

abstract class Shape
{
    public abstract double Area();
}

class Circle : Shape
{
    double radius;

    public Circle(double r)
    {
        radius = r;
    }

    public override double Area()
    {
        return 3.14 * radius * radius;
    }
}

class Rectangle : Shape
{
    double length;
    double width;

    public Rectangle(double l, double w)
    {
        length = l;
        width = w;
    }

    public override double Area()
    {
        return length * width;
    }
}

在上面的代码中,我们定义了一个抽象的 Shape 类,然后 CircleRectangle 类都继承自 Shape 类。同时,Shape 类中定义了一个抽象的 Area() 方法。CircleRectangle 类都实现了这个方法。

然后我们可以创建一个 List<Shape> 来表示各种形状的图形,然后计算它们的面积。

List<Shape> shapes = new List<Shape>();
shapes.Add(new Circle(3));
shapes.Add(new Rectangle(4, 5));

foreach (Shape shape in shapes)
{
    Console.WriteLine("面积是:" + shape.Area());
}

输出结果如下:

面积是:28.26
面积是:20

我们可以看到,由于 CircleRectangle 类都实现了 Area() 方法,调用 List<Shape> 类型的对象的 Area() 方法时,会根据实际执行的对象来调用对应的方法。这种由对象的实际类型来决定方法的调用方式,也是运行时多态。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# 最基础知识介绍–多态 - Python技术站

(0)
上一篇 2023年6月1日
下一篇 2023年6月1日

相关文章

  • .NET 实现 JWT 登录验证

    .NET 实现JWT登录认证 在ASP.NET Core应用程序中,使用JWT进行身份验证和授权已成为一种流行的方式。JWT是一种安全的方式,用于在客户端和服务器之间传输用户信息。 添加NuGet包 首先,我们需要添加一些NuGet包来支持JWT身份验证。在您的ASP.NET Core项目中,打开Startup.cs文件,并在ConfigureService…

    C# 2023年4月22日
    00
  • jQuery+Asp.Net实现省市二级联动功能的方法

    下面是关于“jQuery+Asp.Net实现省市二级联动功能的方法”的完整攻略: 一、前置知识 在实现该功能前,你需要具备以下前置知识: HTML、CSS基本语法 jQuery基本用法 Asp.Net基本知识 二、具体实现步骤 1. 在HTML页面中添加表单元素 首先,在HTML页面中添加两个下拉框,分别用来显示“省份”和“城市”。HTML代码如下: &lt…

    C# 2023年5月31日
    00
  • C#中的SQLCommand命令与DbTransaction事务处理

    关于C#中的SQLCommand命令与DbTransaction事务处理,我可以提供如下完整攻略: 简介 在C#语言中,我们常常需要操作数据库进行增、删、改、查等操作。其中,SQLCommand命令是一种常用的操作方式,可以在C#应用程序中执行SQL语句。而DbTransaction则可以提供 数据库事务 的支持,它可以保证一组数据的操作要么全部成功,要么全…

    C# 2023年6月1日
    00
  • asp.net中生成缩略图并添加版权实例代码

    你需要掌握以下内容: 通过使用 System.Drawing 命名空间,将图片文件读入 Bitmap 对象。 创建一个新的 Bitmap 对象,调用 Graphics 对象将原始图片画到新的 Bitmap 对象上,并指定新的大小。 通过 Image.Save 方法将缩略图保存为新的文件。 添加版权信息。 下面是示例代码和详细步骤: 1. 通过使用 Syste…

    C# 2023年5月31日
    00
  • Netcore Webapi返回数据的三种方式示例

    下面我来介绍一下“Netcore Webapi返回数据的三种方式示例”的完整攻略。 概述 在开发Webapi时经常需要返回各种数据,例如字符串、Json格式数据、XML格式数据、二进制文件、图片等等。本篇文章将介绍Netcore Webapi返回数据的三种方式示例,分别为返回字符串、返回Json格式数据和返回文件。 返回字符串 在Webapi中,返回字符串最…

    C# 2023年6月3日
    00
  • C#中发送邮件代码

    让我们来详细讲解一下C#中发送邮件代码的完整攻略吧。 1.准备工作 在C#中发送邮件,需要使用到SmtpClient类和MailMessage类,它们位于命名空间System.Net.Mail中,所以需要先在代码中导入该命名空间。 using System.Net.Mail; 2.发送邮件 2.1 简单邮件 下面我们通过一个简单的例子来演示如何使用C#发送一…

    C# 2023年6月7日
    00
  • C#使用NPOI实现Excel和DataTable的互转

    这里是使用NPOI实现Excel和DataTable互转的完整攻略,包括具体的步骤和两条示例说明。 1. 安装NPOI库 首先需要安装NPOI库,可以使用NuGet进行安装。在Visual Studio中打开NuGet控制台,输入以下命令来安装NPOI库: Install-Package NPOI 2. 读取Excel文件 读取Excel文件可以使用HSSF…

    C# 2023年5月31日
    00
  • 使用 CliWrap 让C#中的命令行交互(推荐)

    使用 CliWrap 是一种方便、简单,并且推荐的 C# 调用命令行工具的方式。CliWrap 提供了一个类 CliWrap.Cli,该类封装了启动外部程序和与其进行交互的逻辑。 安装 要使用 CliWrap,需要将它添加到 C# 项目中。添加的方式有以下两种: NuGet:通过 NuGet 包管理器安装 CliWrap。打开 Visual Studio,打…

    C# 2023年6月7日
    00
合作推广
合作推广
分享本页
返回顶部