首页 > 系统相关 >windows C#-多态性

windows C#-多态性

时间:2024-11-10 20:18:07浏览次数:3  
标签:windows 多态性 DoWork 派生类 class C# 基类 new public

多态性常被视为自封装和继承之后,面向对象的编程的第三个支柱。 Polymorphism(多态性)是一个希腊词,指“多种形态”,多态性具有两个截然不同的方面:

  • 在运行时,在方法参数和集合或数组等位置,派生类的对象可以作为基类的对象处理。 在出现此多形性时,该对象的声明类型不再与运行时类型相同;
  • 基类可以定义并实现虚方法,派生类可以重写这些方法,即派生类提供自己的定义和实现。 在运行时,客户端代码调用该方法,CLR 查找对象的运行时类型,并调用虚方法的重写方法。 你可以在源代码中调用基类的方法,执行该方法的派生类版本;

虚方法允许你以统一方式处理多组相关的对象。 例如,假定你有一个绘图应用程序,允许用户在绘图图面上创建各种形状。 你在编译时不知道用户将创建哪些特定类型的形状。 但应用程序必须跟踪创建的所有类型的形状,并且必须更新这些形状以响应用户鼠标操作。 你可以使用多态性通过两个基本步骤解决这一问题:

  • 创建一个类层次结构,其中每个特定形状类均派生自一个公共基类;
  • 使用虚方法通过对基类方法的单个调用来调用任何派生类上的相应方法;

首先,创建一个名为 RectangleShape 的基类,并创建一些派生类,例如 TriangleCircle、 和 。 为 Shape 类提供一个名为 Draw 的虚拟方法,并在每个派生类中重写该方法以绘制该类表示的特定形状。 创建 List<Shape> 对象,并向其添加 Circle、Triangle 和 Rectangle。

public class Shape
{
    // A few example members
    public int X { get; private set; }
    public int Y { get; private set; }
    public int Height { get; set; }
    public int Width { get; set; }

    // Virtual method
    public virtual void Draw()
    {
        Console.WriteLine("Performing base class drawing tasks");
    }
}

public class Circle : Shape
{
    public override void Draw()
    {
        // Code to draw a circle...
        Console.WriteLine("Drawing a circle");
        base.Draw();
    }
}
public class Rectangle : Shape
{
    public override void Draw()
    {
        // Code to draw a rectangle...
        Console.WriteLine("Drawing a rectangle");
        base.Draw();
    }
}
public class Triangle : Shape
{
    public override void Draw()
    {
        // Code to draw a triangle...
        Console.WriteLine("Drawing a triangle");
        base.Draw();
    }
}

若要更新绘图图面,请使用 foreach 循环对该列表进行循环访问,并对其中的每个 Shape 对象调用 Draw 方法。 虽然列表中的每个对象都具有声明类型 Shape,但调用的将是运行时类型(该方法在每个派生类中的重写版本)。

// Polymorphism at work #1: a Rectangle, Triangle and Circle
// can all be used wherever a Shape is expected. No cast is
// required because an implicit conversion exists from a derived
// class to its base class.
var shapes = new List<Shape>
{
    new Rectangle(),
    new Triangle(),
    new Circle()
};

// Polymorphism at work #2: the virtual method Draw is
// invoked on each of the derived classes, not the base class.
foreach (var shape in shapes)
{
    shape.Draw();
}
/* Output:
    Drawing a rectangle
    Performing base class drawing tasks
    Drawing a triangle
    Performing base class drawing tasks
    Drawing a circle
    Performing base class drawing tasks
*/

在 C# 中,每个类型都是多态的,因为包括用户定义类型在内的所有类型都继承自 Object。

多形性概述
虚拟成员

当派生类从基类继承时,它包括基类的所有成员。 基类中声明的所有行为都是派生类的一部分。 这使派生类的对象能够被视为基类的对象。 访问修饰符(public、protected、private 等)确定是否可以从派生类实现访问这些成员。 通过虚拟方法,设计器可以选择不同的派生类行为:

派生类可以重写基类中的虚拟成员,并定义新行为。
派生类可能会继承最接近的基类方法而不重写方法,同时保留现有的行为,但允许进一步派生的类重写方法。
派生类可以定义隐藏基类实现的成员的新非虚实现。
仅当基类成员声明为 virtual 或 abstract 时,派生类才能重写基类成员。 派生成员必须使用 override 关键字显式指示该方法将参与虚调用。 以下代码提供了一个示例:

public class BaseClass
{
    public virtual void DoWork() { }
    public virtual int WorkProperty
    {
        get { return 0; }
    }
}
public class DerivedClass : BaseClass
{
    public override void DoWork() { }
    public override int WorkProperty
    {
        get { return 0; }
    }
}

字段不能是虚拟的,只有方法、属性、事件和索引器才可以是虚拟的。 当派生类重写某个虚拟成员时,即使该派生类的实例被当作基类的实例访问,也会调用该成员。 以下代码提供了一个示例:

DerivedClass B = new DerivedClass();
B.DoWork();  // Calls the new method.

BaseClass A = B;
A.DoWork();  // Also calls the new method.

虚方法和属性允许派生类扩展基类,而无需使用方法的基类实现。 接口提供另一种方式来定义将实现留给派生类的方法或方法集。

使用新成员隐藏基类成员

如果希望派生类具有与基类中的成员同名的成员,则可以使用 new 关键字隐藏基类成员。 new 关键字放置在要替换的类成员的返回类型之前。 以下代码提供了一个示例

public class BaseClass
{
    public void DoWork() { WorkField++; }
    public int WorkField;
    public int WorkProperty
    {
        get { return 0; }
    }
}

public class DerivedClass : BaseClass
{
    public new void DoWork() { WorkField++; }
    public new int WorkField;
    public new int WorkProperty
    {
        get { return 0; }
    }
}

通过将派生类的实例强制转换为基类的实例,可以从客户端代码访问隐藏的基类成员。 例如:

DerivedClass B = new DerivedClass();
B.DoWork();  // Calls the new method.

BaseClass A = (BaseClass)B;
A.DoWork();  // Calls the old method.
阻止派生类重写虚拟成员

无论在虚拟成员和最初声明虚拟成员的类之间已声明了多少个类,虚拟成员都是虚拟的。 如果类 A 声明了一个虚拟成员,类 B 从 A 派生,类 C 从类 B 派生,则不管类 B 是否为虚拟成员声明了重写,类 C 都会继承该虚拟成员,并可以重写它。 以下代码提供了一个示例:

public class A
{
    public virtual void DoWork() { }
}
public class B : A
{
    public override void DoWork() { }
}

派生类可以通过将重写声明为 sealed 来停止虚拟继承。 停止继承需要在类成员声明中的 override 关键字前面放置 sealed 关键字。 以下代码提供了一个示例:

public class C : B
{
    public sealed override void DoWork() { }
}

在上一个示例中,方法 DoWork 对从 C 派生的任何类都不再是虚拟方法。 即使它们转换为类型 B 或类型 A,它对于 C 的实例仍然是虚拟的。 通过使用 new 关键字,密封的方法可以由派生类替换,如下面的示例所示:

public class D : C
{
    public new void DoWork() { }
}

在此情况下,如果在 D 中使用类型为 D 的变量调用 DoWork,被调用的将是新的 DoWork。 如果使用类型为 C、B 或 A 的变量访问 D 的实例,对 DoWork 的调用将遵循虚拟继承的规则,即把这些调用传送到类 C 的 DoWork 实现。

从派生类访问基类虚拟成员

已替换或重写某个方法或属性的派生类仍然可以使用 base 关键字访问基类的该方法或属性。 以下代码提供了一个示例:

public class Base
{
    public virtual void DoWork() {/*...*/ }
}
public class Derived : Base
{
    public override void DoWork()
    {
        //Perform Derived's work here
        //...
        // Call DoWork on base class
        base.DoWork();
    }
}

标签:windows,多态性,DoWork,派生类,class,C#,基类,new,public
From: https://blog.csdn.net/m0_72813396/article/details/143444555

相关文章

  • windows C#-继承
    继承(以及封装和多态性)是面向对象的编程的三个主要特征之一。通过继承,可以创建新类,以便重用、扩展和修改在其他类中定义的行为。其成员被继承的类称为“基类”,继承这些成员的类称为“派生类”。派生类只能有一个直接基类。但是,继承是可传递的。如果ClassC派生自ClassB......
  • windows C#-对象
    类或结构定义的作用类似于蓝图,指定该类型可以进行哪些操作。从本质上说,对象是按照此蓝图分配和配置的内存块。程序可以创建同一个类的多个对象。对象也称为实例,可以存储在命名变量中,也可以存储在数组或集合中。使用这些变量来调用对象方法及访问对象公共属性的代码称为客户......
  • windows C#-匿名类型
    匿名类型提供了一种方便的方法,可用来将一组只读属性封装到单个对象中,而无需首先显式定义一个类型。类型名由编译器生成,并且不能在源代码级使用。每个属性的类型由编译器推断。可结合使用new运算符和对象初始值设定项创建匿名类型。 以下示例显示了用两个名为Amount和......
  • 小北的字节跳动青训营与LangChain实战课:深入探索Chain的奥秘(上)写一篇完美鲜花推文?用Se
     前言    最近,字节跳动的青训营再次扬帆起航,作为第二次参与其中的小北,深感荣幸能借此机会为那些尚未了解青训营的友友们带来一些详细介绍。青训营不仅是一个技术学习与成长的摇篮,更是一个连接未来与梦想的桥梁~小北的青训营XMarsCode技术训练营——AI加码,字节跳......
  • 【优化求解】蚁群算法ACO求解经济损失的航班延误恢复优化问题(目标函数:航班延误成本最
    ......
  • 【CRM系统选型指南:国内八大主流工具比较】
    本文将对十大主流CRM系统进行比较:纷享销客、ZohoCRM、Pipedrive、简信CRM、HubSpotCRM、八百客CRM、金蝶CRM、浪潮CRM、销售易CRM本文将深入评比2024年主流的CRM系统,帮助你了解各系统之间的主要区别、优缺点以及当前的发展趋势。通过详细的比较和分析,为你提供一个清晰的......
  • 【Python知识宝库】快速了解 `isinstance()` 的原理、作用和使用场景
    ......
  • C++实现命令行文本计数统计程序
    附上一位博主写的关于git的使用(个人感觉非常完整,对新手很友好):Git及Tortoisegit下载安装及使用详细配置过程_tortoisegit下载远程代码-CSDN博客 Gitee地址:https://gitee.com/wnmdsqwnhkmc/second-assignment注:本文并不包含主函数,完整代码请移步Gitee路径:[项目>>ConsoleAppl......
  • MDPI之Applied Science word 模板下载
    因为之前找过很多资料,都没有word模板下载的教程,所以在这里留个记号。官网点此一、进入如下页面 二、下拉找到Submissionchecklist在这里有 MicrosoftWord模板和 LaTeX模板(在此处单击或去官网点击即可自行下载)。......
  • docker的使用(使用docker部署ctf题目)
    最近实验室要举办一次ctf竞赛,本人web手兼杂项手,杂项的题在服务器上传附件就行,比较好弄,然后web的题目需要docker部署,就学了一下docker,前前后后忙了一天多,做了很多无用功。我太菜鸡了。记录一下配置过程还有docker的一些知识点。(学习尚浅,希望路过的大佬多多指导)0X01什么是DockerD......