要扩展或修改继承的方法、属性、索引器或事件的抽象实现或虚实现,必须使用 override 修饰符。

在此例中,类 Square 必须提供 Area 的重写实现,因为 Area 是从抽象的 ShapesClass 继承而来的。

abstract class ShapesClass
{
    abstract public int Area();
}

class Square : ShapesClass
{
    int x, y;
    // Because ShapesClass.Area is abstract, failing to override
    // the Area method would result in a compilation error.
    public override int Area()
    {
        return x * y;
    }
}
有关 override 关键字用法的更多信息,请参见使用 Override 和 New 关键字进行版本控制以及了解何时使用 Override 和 New 关键字。

备注override 方法提供从基类继承的成员的新实现。通过 override 声明重写的方法称为重写基方法。重写的基方法必须与 override 方法具有相同的签名。有关继承的信息,请参见继承。

不能重写非虚方法或静态方法。重写的基方法必须是 virtual、abstract 或 override 的。

override 声明不能更改 virtual 方法的可访问性。override 方法和 virtual 方法必须具有相同的访问级别修饰符。

不能使用修饰符 new、static、virtual 或 abstract 来修改 override 方法。

重写属性声明必须指定与继承属性完全相同的访问修饰符、类型和名称,并且被重写的属性必须是 virtual、abstract 或 override 的。
示例此示例定义了一个名为 Employee 的基类,和一个名为 SalesEmployee 的派生类。SalesEmployee 类包括一个额外的属性 salesbonus,并重写方法 CalculatePay 以便将该属性考虑在内。

using System;
class TestOverride
{
    public class Employee
    {
        public string name;

// Basepay is defined as protected, so that it may be 
        // accessed only by this class and derrived classes.
        protected decimal basepay;

// Constructor to set the name and basepay values.
        public Employee(string name, decimal basepay)
        {
            this.name = name;
            this.basepay = basepay;
        }

// Declared virtual so it can be overridden.
        public virtual decimal CalculatePay()
        {
            return basepay;
        }
    }

// Derive a new class from Employee.
    public class SalesEmployee : Employee
    {
        // New field that will affect the base pay.
        private decimal salesbonus;

// The constructor calls the base-class version, and
        // initializes the salesbonus field.
        public SalesEmployee(string name, decimal basepay, 
                  decimal salesbonus) : base(name, basepay)
        {
            this.salesbonus = salesbonus;
        }

// Override the CalculatePay method 
        // to take bonus into account.
        public override decimal CalculatePay()
        {
            return basepay + salesbonus;
        }
    }

static void Main()
    {
        // Create some new employees.
        SalesEmployee employee1 = new SalesEmployee("Alice", 
                      1000, 500);
        Employee employee2 = new Employee("Bob", 1200);

Console.WriteLine("Employee " + employee1.name + 
                  " earned: " + employee1.CalculatePay());
        Console.WriteLine("Employee " + employee2.name + 
                  " earned: " + employee2.CalculatePay());
    }
}
输出
Employee Alice earned: 1500
Employee Bob earned: 1200
使用 Override 和 New 关键字进行版本控制(C# 编程指南) C# 语言经过专门设计,以便不同库中的基类与派生类之间的版本控制可以不断向前发展,同时保持向后兼容。这具有多方面的意义。例如,这意味着在基类中引入与派生类中的某个成员具有相同名称的新成员在 C# 中是完全支持的,不会导致意外行为。它还意味着类必须显式声明某方法是要重写一个继承方法,还是一个仅隐藏具有类似名称的继承方法的新方法。C# 允许派生类包含与基类方法名称相同的方法。基类方法必须定义为 virtual。如果派生类中的方法前面没有 new 或 override 关键字,则编译器将发出警告,该方法将有如存在 new 关键字一样执行操作。如果派生类中的方法前面带有 new 关键字,则该方法被定义为独立于基类中的方法。如果派生类中的方法前面带有 override 关键字,则派生类的对象将调用该方法,而不调用基类方法。可以从派生类中使用 base 关键字调用基类方法。override、virtual 和 new 关键字还可以用于属性、索引器和事件中。默认情况下,C# 方法不是虚方法 -- 如果将一种方法声明为虚方法,则继承该方法的任何类都可以实现其自己的版本。若要使方法成为虚方法,必须在基类的方法声明中使用 virtual 修饰符。然后,派生类可以使用 override 关键字重写基虚方法,或使用 new 关键字隐藏基类中的虚方法。如果 override 关键字和 new 关键字均未指定,编译器将发出警告,并且派生类中的方法将隐藏基类中的方法。有关更多信息,请参见编译器警告 CS0108。为了在实践中演示上述情况,我们暂时假定公司 A 创建了一个名为 GraphicsClass 的类,您的程序使用该类。GraphicsClass 类似如下:C#class GraphicsClass
{
    public virtual void DrawLine() { }
    public virtual void DrawPoint() { }
}

您的公司使用此类,并且您在添加新方法时将其用来派生自己的类:

C#

class YourDerivedGraphicsClass : GraphicsClass
{
    public void DrawRectangle() { }
}

您在应用程序的使用过程中没有遇到任何问题,直到公司 A 发布了 GraphicsClass 的新版本,该新版本类似如下:

C#

class GraphicsClass
{
    public virtual void DrawLine() { }
    public virtual void DrawPoint() { }
    public virtual void DrawRectangle() { }
}

现在,GraphicsClass 的新版本中包含了一个称为 DrawRectangle 的方法。最初,一切正常。新版本仍与旧版本二进制兼容 -- 即使在计算机系统中安装新类,部署的所有软件仍将继续工作。在您的派生类中,对方法 DrawRectangle 的任何现有调用将继续引用您的版本。
但是,一旦使用 GraphicsClass 的新版本重新编译应用程序,您将收到来自编译器的警告。有关更多信息,请参见编译器警告 CS0108。
此警告提示您需要考虑您的 DrawRectangle 方法在应用程序中的工作方式。
如果想用您的方法重写新的基类方法,请使用 override 关键字,如下所示:

C#

class YourDerivedGraphicsClass : GraphicsClass
{
    public override void DrawRectangle() { }
}

override 关键字可确保派生自 YourDerivedGraphicsClass 的任何对象都将使用 DrawRectangle 的派生类版本。派生自 YourDerivedGraphicsClass 的对象仍可以使用 base 关键字访问 DrawRectangle 的基类版本,如下所示:

C#

base.DrawRectangle();

如果不想用您的方法重写新的基类方法,则应注意下面的事项。为避免在两种方法之间引起混淆,可以重命名您的方法。重命名方法可能很耗时且容易出错,而且在某些情况下并不实用。但是,如果您的项目相对较小,则可以使用 Visual Studio 的重构选项来重命名方法。有关更多信息,请参见重构类和类型。
或者,也可以通过在派生类定义中使用关键字 new 来防止出现该警告,如下所示:

C#

class YourDerivedGraphicsClass : GraphicsClass
{
    public new void DrawRectangle() { }
}

使用 new 关键字告诉编译器您的定义将隐藏基类中包含的定义。这是默认行为。
重写和方法选择

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

C#

public class Derived : Base
{
    public override void DoWork(int param) { }
    public void DoWork(double param) { }
}

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

C#

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) 的实现。例如:

C#

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

c# override用法的更多相关文章

  1. Kotlin基础(三)类、对象和接口

    类.对象和接口 一.定义类的继承结构 一)Kotlin中的接口 Kotlin的接口与Java8中相似,它们可以包含抽象方法的定义以及非抽象方法的实现,但它们不能包含任何状态. interface Cl ...

  2. Java高并发系列——检视阅读

    Java高并发系列--检视阅读 参考 java高并发系列 liaoxuefeng Java教程 CompletableFuture AQS原理没讲,需要找资料补充. JUC中常见的集合原来没讲,比如C ...

  3. Java魔法堂:注解用法详解——@Override

    一.前言 现在有Son和Parent两个类,且类型Son将会重写类型Parent的getName函数.但不幸的是由于码农大意,写成如下代码: public class Parent{ public S ...

  4. @Override在JDK1.5和JDK1.6中用法区别

    @Override 注解在jdk1.5环境下,只能用于对基类(父类)的方法的重写.而不能用于对实现的接口的方法的实现.而在jdk1.6环境下,两者都适用.

  5. c#中virtual, abstract和override的区别和用法

    virtual是把一个方法声明为虚方法,使派生类可重写此方法,一般建立的方法是不能够重写的,譬如类A中有个方法protected void method(){ 原代码....;}类B继承自类A,类B能 ...

  6. C#继承中的override(重写)与new(覆盖)用法

    刚接触C#编程,我也是被override与new搞得晕头转向.于是花了点时间翻资料,看博客,终于算小有领悟,把学习笔记记录于此. 首先声明一个父类Animal类,与继承Animal的两个子类Dog类与 ...

  7. 【react表格组件】material-table 基本用法 & 组件override

    教程: https://mbrn.github.io/material-table/#/ https://material-ui.com/api/table/ github: https://gith ...

  8. C# 关键字 virtual、override和new的用法

    代码如下: class A { public void foo() { Console.WriteLine("A::foo()"); } public virtual void b ...

  9. C++ 虚函数表与多态 —— 关键字 override 的用法

    override 仅能用于虚函数,他属于C++新特性,是重写覆盖的意思,他的存在仅仅是为了提高代码的可阅读性: 作用: 1. 提示程序的阅读者,这个函数是重写父类的功能. 2. 防止程序员在重写父类的 ...

随机推荐

  1. Android Camera2 拍照(二)——使用TextureView

    原文:Android Camera2 拍照(二)--使用TextureView 上一篇博文简单介绍了使用Camera2 API拍摄照片,并使用SurfaceView作为预览界面.实际上,相对于Surf ...

  2. C#串口控制舵机、arduino源码 及C#源码及界面

    原文 C#串口控制舵机.arduino源码 及C#源码及界面 1.舵机原理简介 控制信号由接收机的通道进入信号调制芯片,获得直流偏置电压.它内部有一个基准电路,产生周期为20ms,宽度为1.5ms的基 ...

  3. imp dll时遇见的非常恶心的问题

    我需要导入dll库中这样一个函数VM661JTCPDLL_API int admin_login(sel_admin_ret* sel_admins, int num, char* admin_nam ...

  4. 使用Newtonsoft.Json输出JSON

    安装: Install-Package Newtonsoft.Json 代码: //序列化DataTable DataTable dt = new DataTable(); dt.Columns.Ad ...

  5. 解决手机提示TF卡受损需要格式化问题

    昨晚因为上QQ FOR PAD后.关机.结果又杯具了.上次无意看到一个SD卡修复命令,收藏起来了.一试,还真管用.现把它写出来.分享给大家.以后出现SD卡受损,千万不要再格式化内存卡了.修复过程:1. ...

  6. Android零基础入门第59节:AnalogClock、DigitalClock和TextClock时钟组件

    原文:Android零基础入门第59节:AnalogClock.DigitalClock和TextClock时钟组件 在前面一期,我们学习了DatePicker和TimePicker,在实际开发中其不 ...

  7. vmstat命令浅析

    vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况.这个命令是我查看Linux/Unix最 ...

  8. VC 使用msxml6.dll动态链接库中的函数读写XML文件

    VC 使用msxml6.dll动态链接库中的函数读写XML文件 目录 1 引言 2 .dll使用方法 3 常用函数总结 4 实例应用 5 运行效果预览 6 补充说明 7 不足之处 8 更新   引言: ...

  9. VS2010使用c++、gSOAP创建WebService 图文教程

    VS2010使用c++.gSOAP创建的WebService 图文教程 环境 操作系统:Windows 7gsoap版本:2.8.32C++编译器/开发环境:Visual Studio 2010 gS ...

  10. CAP碎碎念

    整个2017年都在搞大数据平台,完全远离了机器学习,甚至都不记得写过类似ETL的job. 从数据到平台,从业务处理到基础服务. Metrics的收集,报警,生成报表.Data pipeline的准确性 ...