C# 语言经过专门设计,以便不同库中的基类与派生类之间的版本控制可以不断向前发展,同时保持向后兼容。这具有多方面的意义。例如,这意味着在基中引入与派生类中的某个成员具有相同名称的新成员在 C# 中是完全支持的,不会导致意外行为。它还意味着类必须显式声明某方法是要重写一个继承方法,还是一个仅隐藏具有类似名称的继承方法的新方法。

C# 允许派生类包含与基类方法名称相同的方法。

  • 基类方法必须定义为 virtual
  • 如果派生类中的方法前面没有 newoverride 关键字,则编译器将发出警告,该方法将有如存在 new 关键字一样执行操作。
  • 如果派生类中的方法前面带有 new 关键字,则该方法被定义为独立于基类中的方法。
  • 如果派生类中的方法前面带有 override 关键字,则派生类的对象将调用该方法,而不调用基类方法。
  • 可以从派生类中使用 base 关键字调用基类方法。
  • override、virtual 和 new 关键字还可以用于属性、索引器和事件中。

默认情况下,C# 方法不是虚方法 -- 如果将一种方法声明为虚方法,则继承该方法的任何类都可以实现其自己的版本。若要使方法成为虚方法,必须在基类的方法声明中使用 virtual 修饰符。然后,派生类可以使用 override 关键字重写基虚方法,或使用 new 关键字隐藏基类中的虚方法。如果 override 关键字和 new 关键字均未指定,编译器将发出警告,并且派生类中的方法将隐藏基类中的方法。

何时用override:MSDN例子

// Define the base class

class Car

{

public virtual void DescribeCar()

{

System.Console.WriteLine("Four wheels and an engine.");

}

}

// Define the derived classes

class ConvertibleCar : Car

{

public new virtual void DescribeCar()

{

base.DescribeCar();

System.Console.WriteLine("A roof that opens up.");

}

}

class Minivan : Car

{

public override void DescribeCar()

{

base.DescribeCar();

System.Console.WriteLine("Carries seven people.");

}

}

Static void Main()

{

foreach (Car vehicle in cars)

{

System.Console.WriteLine("Car object: " + vehicle.GetType());

vehicle.DescribeCar();

System.Console.WriteLine("----------");

}

}

首先声明三个类:一个名为 Car 的类以及从该基类派生的两个类 ConvertibleCar 和 Minivan。基类包含一个可将有关汽车的描述发送到控制台的方法 (DescribeCar)。派生类方法也包含一个名为 DescribeCar 的方法,该方法显示派生类的独特属性。这些方法还调用基类的 DescribeCar 方法来演示从 Car 类继承属性的方式。

重写

当在类中指定方法时,如果有多个方法与调用兼容(例如,存在两种同名的方法,并且其参数与传递的参数兼容),则 C# 编译器将选择最佳方法进行调用。下面的方法将是兼容的:

public class Derived : Base

{

public override void DoWork(int param) { }

public void DoWork(double param) { }

}

在 Derived 的一个实例中调用 DoWork 时,C# 编译器将首先尝试使该调用与最初在 Derived 上声明的 DoWork 版本兼容。重写方法不被视为是在类上进行声明的,而是在基类上声明的方法的新实现。仅当 C# 编译器无法将方法调用与 Derived 上的原始方法匹配时,它才尝试将该调用与具有相同名称和兼容参数的重写方法匹配。例如:

int val = 5;

Derived d = new Derived();

d.DoWork(val);  // Calls DoWork(double).

由于变量 val 可以隐式转换为 double 类型,因此 C# 编译器将调用 DoWork(double),而不是 DoWork(int)。有两种方法可以避免此情况。首先,避免将新方法声明为与虚方法同名。其次,可以通过将 Derived 的实例强制转换为 Base 来使 C# 编译器搜索基类方法列表,从而使其调用虚方法。由于是虚方法,因此将调用 Derived 上的 DoWork(int) 的实现。例如:

((Base)d).DoWork(val);  // Calls DoWork(int) on Derived.

多态在C#中的应用的更多相关文章

  1. 从认识面向对象到构造函数的标准写法(构造函数的继承、多态、ECMA6中新代替语法class) - 下

    笔记一个包含:认识面向对象.构造函数的封装.继承.多态.ECMA6中新代替语法class 下:包括构造函数的继承.多态.ECMA6中新代替语法class 构造函数的继承 从父一级延续下来的属性和功能( ...

  2. Java多态与C++中多态的实现

    大牛的文章,值得拜读http://www.ibm.com/developerworks/cn/java/j-lo-polymorph/ 粘贴过来好多图片丢失了 /(ㄒoㄒ)/~~ 众所周知,多态是面向 ...

  3. 论python3下“多态”与“继承”中坑

    1.背景: 近日切换到python3后,发现python3在多态处理上,有一些比较有意思的情况,特别记载,供大家参考... 以廖老师的python3教程中的animal 和dog的继承一节的代码做例子 ...

  4. IOS多态在项目中的应用

    今天我们讲述一个知识点(大家可能遗漏的) 多态是面试程序设计(OOP)一个重要特征,但在iOS中,可能比较少的人会留意这个特征,实际上在开发中我们可能已经不经意的使用了多态.比如说: 有一个table ...

  5. 四. Java继承和多态3. 继承中的方法的覆盖和重载

    在类继承中,子类可以修改从父类继承来的方法,也就是说子类能创建一个与父类方法有不同功能的方法,但具有相同的名称.返回值类型.参数列表. 如果在新类中定义一个方法,其名称.返回值类型和参数列表正好与父类 ...

  6. C#中的接口实现多态

    我们都知道虚方法实现多态,抽象方法实现多态等,我们今天来看看如何使用接口实现多态 1.首先我们先要来了解了解什么是接口,它存在的意识 01.接口就是为了约束方法的格式(参数和返回值类型)而存在的 02 ...

  7. java中静态属性和和静态方法的继承问题 以及多态的实质

    首先结论是:java中静态属性和和静态方法可以被继承,但是没有被重写(overwrite)而是被隐藏. 静态方法和属性是属于类的,调用的时候直接通过类名.方法名完成的,不需继承机制就可以调用如果子类里 ...

  8. java多态中哪些成员具备多态特性

    在多态的学习中,当子类继承父类时,子类中的变量哪些具备多态特性,哪些不具备多特特性. 代码: class Father{ public static int x=10; public int y=11 ...

  9. JAVA之旅(八)——多态的体现,前提,好处,应用,转型,instanceof,多态中成员变量的特点,多态的案例

    JAVA之旅(八)--多态的体现,前提,好处,应用,转型,instanceof,多态中成员变量的特点,多态的案例 学习是不能停止的 一.多态 我们今天又要学习一个新的概念了,就是多态,它是面向对象的第 ...

随机推荐

  1. 猪齿鱼 Choerodon 的数据初始化设计解析

    数智化效能平台猪齿鱼Choerodon 作为一个微服务框架,需要解决微服务数据初始化本身具有的问题和复杂性,同时也需要满足框架本身特有的数据初始化需求,下面为大家介绍一下这方面的设计思想和实现. 微服 ...

  2. hbase region, store, storefile和列簇,的关系

    先来一张大图. Hbase上Regionserver的内存分为两个部分,一部分作为Memstore,主要用来写:另外一部分作为BlockCache,主要用于读数据:这里主要介绍写数据的部分,即Mems ...

  3. Filter的拦截路径

    Filter的拦截路径 精确匹配 <url-pattern>/target.jsp</url-pattern> 以上配置的路径,表示请求地址必须为:http://ip.port ...

  4. K8s 资源配额管理对象 ResourcesQuota

    Kubernetes 是一个多租户平台,更是一个镜像集群管理工具.一个 Kubernetes 集群中的资源一般是由多个团队共享的,这时候经常要考虑的是如何对这个整体资源进行分配.在 kubernete ...

  5. Java 锁 概念介绍

    一   Java中的锁是什么? /* * 一 Java锁定义? * 在计算机科学中,锁(lock)或互斥(mutex)是一种同步机制,用于在有许多执行线程的环境中强制对资源的访问限制. * 锁旨在强制 ...

  6. Lesson1——Pandas是什么

    pandas目录 一.简介 Pandas 是一个开源的第三方 Python 库,从 Numpy 和 Matplotlib 的基础上构建而来,享有数据分析"三剑客之一"的盛名(Num ...

  7. Atcoder ARC-063

    ARC063(2020.7.16) A \(A\) 题如果洛谷评分很低就不看了. B 可以发现一定是选择在一个地方全部买完然后在之后的一个地方全部卖完,那么我们就只需要即一个后缀最大值就可以计算答案了 ...

  8. Java程序设计(2021春)——第五章输入输出笔记与思考

    Java程序设计(2021春)--第五章输入输出笔记与思考 本章概览: 异常处理简介 程序运行时,环境.操作等可能出现各种错误.故障,我们希望程序具有容错能力,给出错误信息.面向对象的程序设计里有异常 ...

  9. JSP response.setCharacterEncoding与response.setContentType的区别

    问题描述 昨天在参考别人的项目时,发现页面引用js,css等文件总是乱码,后来才发现是MIME类型统一设置为text/html,并且仅仅编码设置了浏览器端的解析编码.另外,可以先通过文本编辑器(如no ...

  10. bom-简单动画

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...