首页 > 编程语言 >C#多态【转载收藏】

C#多态【转载收藏】

时间:2023-04-21 11:22:28浏览次数:26  
标签:成员 C# DoWork 派生类 多态 基类 new 转载 public

多态性(C# 编程指南)转自MSDN

 

通过继承,一个类可以用作多种类型:可以用作它自己的类型、任何基类型,或者在实现接口时用作任何接口类型。这称为多态性。C# 中的每种类型都是多态的。类型可用作它们自己的类型或用作 Object 实例,因为任何类型都自动将 Object 当作基类型。

多态性不仅对派生类很重要,对基类也很重要。任何情况下,使用基类实际上都可能是在使用已强制转换为基类类型的派生类对象。基类的设计者可以预测到其基类中可能会在派生类中发生更改的方面。例如,表示汽车的基类可能包含这样的行为:当考虑的汽车为小型货车或敞篷汽车时,这些行为将会改变。基类可以将这些类成员标记为虚拟的,从而允许表示敞篷汽车和小型货车的派生类重写该行为。

 

多态性概述

当派生类从基类继承时,它会获得基类的所有方法、字段、属性和事件。面向对象的语言使用虚方法表达多态。若要更改基类的数据和行为,您有两种选择:可以使用新的派生成员替换基成员,或者可以重写虚拟的基成员。

使用新的派生成员替换基类的成员需要使用 new 关键字。如果基类定义了一个方法、字段或属性,则 new 关键字用于在派生类中创建该方法、字段或属性的新定义。new 关键字放置在要替换的类成员的返回类型之前。例如:

 

 1public class BaseClass
 2{
 3    public void DoWork() { }
 4    public int WorkField;
 5    public int WorkProperty
 6    {
 7        get { return 0; }
 8    }
 9}


10public class DerivedClass : BaseClass
11{
12    public new void DoWork() { }
13    public new int WorkField;
14    public new int WorkProperty
15    {
16        get { return 0; }
17    }
18}
19

 

使用 new 关键字时,调用的是新的类成员而不是已被替换的基类成员。这些基类成员称为隐藏成员。如果将派生类的实例强制转换为基类的实例,就仍然可以调用隐藏类成员。例如:

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

BaseClass A = (BaseClass)B;
A.DoWork();  // Calls the old method.

为了使派生类的实例完全接替来自基类的类成员,基类必须将该成员声明为虚拟的。这是通过在该成员的返回类型之前添加 virtual 关键字来实现的。然后,派生类可以选择使用 override 关键字而不是 new,将基类实现替换为它自己的实现。例如:

  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 = (BaseClass)B;
A.DoWork();  // Also calls the new method.

使用虚拟方法和属性可以预先计划未来的扩展。由于在调用虚拟成员时不考虑调用方正在使用的类型,所以派生类可以选择完全更改基类的外观行为。

无论在派生类和最初声明虚拟成员的类之间已声明了多少个类,虚拟成员都将永远为虚拟成员。如果类 A 声明了一个虚拟成员,类 B 从 A 派生,类 C 从类 B 派生,则类 C 继承该虚拟成员,并且可以选择重写它,而不管类 B 是否为该成员声明了重写。例如:

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

派生类可以通过将重写声明为密封的来停止虚拟继承。这需要在类成员声明中将 sealed 关键字放在 override 关键字的前面。例如:

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

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

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

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

已替换或重写某个方法或属性的派生类仍然可以使用基关键字访问基类的该方法或属性。例如:

  public class A
{
    public virtual void DoWork() { }
}
public class B : A
{
    public override void DoWork() { }
}   public class C : B
{
    public override void DoWork()
    {
        // Call DoWork on B to get B's behavior:
        base.DoWork();

        // DoWork behavior specific to C goes here:
        // ...
    }
}

注意

建议虚拟成员在它们自己的实现中使用 base 来调用该成员的基类实现。允许基类行为发生使得派生类能够集中精力实现特定于派生类的行为。未调用基类实现时,由派生类负责使它们的行为与基类的行为兼容。

 

 

转载:https://www.cnblogs.com/200325074/archive/2008/05/23/1206116.html

 

标签:成员,C#,DoWork,派生类,多态,基类,new,转载,public
From: https://www.cnblogs.com/guzhengtao/p/17339741.html

相关文章

  • 零样本文本分类应用:基于UTC的医疗意图多分类,打通数据标注-模型训练-模型调优-预测部署
    零样本文本分类应用:基于UTC的医疗意图多分类,打通数据标注-模型训练-模型调优-预测部署全流程。1.通用文本分类技术UTC介绍本项目提供基于通用文本分类UTC(UniversalTextClassification)模型微调的文本分类端到端应用方案,打通数据标注-模型训练-模型调优-预测部署全流程,可快速......
  • C#写一套最全的SQL server帮助类(包括增删改查)
    我定义了一系列静态方法,用于执行SQLServer数据库的增删改查等操作。其中:ExecuteNonQuery方法用于执行指定的SQL语句并返回受影响的行数;ExecuteScalar方法用于执行指定的SQL语句并返回查询结果的第一行第一列;ExecuteDataTable方法用于执行指定的SQL语句并返回一个数据表;ExecuteRea......
  • Android-service
    原文地址zhuanlan.zhihu.com残枫cpsService是一种可在后台执行长时间运行操作而不提供界面的应用组件。AndroidServiceAndroidService是组件,既不能说它是单独的进程也不能说它是单独的线程。如果非要从通俗的语言层面来理解的话,姑且将其理解为对象。这个Service对象本......
  • Docker翻脸,不再开源!
    导读前几日,DockerHub出了一件大事!但凡创建了“organisation”的用户都收到了一封含有简短PDF链接的邮件。邮件的内容“金钱味”十足:如果不按照要求升级付费,用户就将失去对数据的访问权限。此举不仅会破坏开源项目的自动化构建,还为一直依赖于开源的用户带来巨大的焦虑和麻烦。......
  • vscode 当做记事本,用任务 tasks 自动提交git - ctrl shift B
    vscode当做记事本,用任务tasks自动提交git-ctrlshiftB起因开始用的joplin本地记事本挺好,唯一缺点不能同步。用了一下,发现markdown是两栏的,变成一栏就是html的。如果要是两栏,我能接受的话,那就直接vscode不就完了吗代码tasks.json{//Seehttps://go.microsof......
  • poi读写EXCEL
    读写EXCEL来源:bilibili狂神说导入依赖<!--导入依赖--><dependencies><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.9</version>......
  • M1 Mac Xcode模拟器无法运行
    from:https://www.jianshu.com/p/87a5cca2a490 新版本的M1芯片运行模拟器报CocoaPods库(如:WechatOpenSDK报arm64错误)错误,是因为M1兼容问题,解决办法有两种如下:强烈推荐方法2方法1:强制打开xcode对x86的支持,有缺点:因为还是采用x86,编译速度很慢。关闭xcode--应用程序--xocde--......
  • C语法
    原文地址zhuanlan.zhihu.comC语法残枫cps​目录收起void指针NULL指针指向指针的指针常量常量指针与指向常量的指针可变参数va_list是类型函数:函数名=函数地址指针函数函数指针函数指针作为参数函数指针作为返回值全局变量extern关键字作用域链接属性void指针NULL......
  • MFC-GetCurrentProcess获取当前进程的伪句柄
     CStringstr;HANDLEhandle=GetCurrentProcess();//获取当前进程的伪句柄/*返回当前进程的伪句柄(始终返回-1)不要直接使用-1这个值,为了将来的兼容性请使用GetCurrentProcess伪句柄可以在当前进程中使用,如果需要跨进程通信,那么必须拿出自己真实......
  • 在线CTF工具箱--端口扫描--杂项--密码学--编码和解码
    这是为CTF发烧者准备的的工具套件,助你过关斩将、攻克难关。目前基础功能和一部分高级功能已经完成,可以在GitHub上查看工具列表和开发进度。 CTFer:https://ctfever.uniiem.com/ 项目地址:https://github.com/UniiemStudio/CTFever ......