C#中override的使用

C#中override的使用

要扩展或修改继承的方法、属性、索引器或事件的抽象实现或虚实现,必须使用 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.

 

转载于:https://www.cnblogs.com/yunzhongniao19915/p/4110658.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/109648.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • JAVA的HelloWorld代码编写

    JAVA的HelloWorld代码编写第一步:新建一个文本文档第二步:打开代码输入代码(注意大小写,Java对大小写很敏感)第三步:更改后缀为.java(这样这个文档就会成为一个原文件)第四步:按住shift键,鼠标右键单击,点击“在此处打开Powershell”第五步:在Powershell窗口里输入JavacHelloworld.java,会出现一个class文档第六步:在Powershell窗口里输入JavacHelloworld会输出HelloWorld…

  • JS–免费刷流量软件工具源码

    JS–免费刷流量软件工具源码<!DOCTYPEHTMLPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head><metahttp-equiv="Content-Type"cont

  • SpringBoot前后端数据传输加密「建议收藏」

    SpringBoot前后端数据传输加密「建议收藏」采用的算法为AES算法1.编写加密工具类packagecom.pibigstar.utils;importjavax.crypto.Cipher;importjavax.crypto.KeyGenerator;importjavax.crypto.spec.SecretKeySpec;importorg.apache.commons.codec.binary.Base…

  • 时间复杂度和空间复杂度详解

    算法的时间复杂度和空间复杂度合称为算法的复杂度。1.时间复杂度(1)时间频度 一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但我们不可能也没有必要对每个算法

    2021年12月25日
  • dirsearch使用_elasticsearch fielddata

    dirsearch使用_elasticsearch fielddatadirsearch配置1.下载地址:https://github.com/maurosoria/dirsearch/archive/master.zip2.安装3.7以上版本python或者gitclonehttps://github.com/maurosoria/dirsearch.gitcddirsearchpip3install-rrequirements.txtpython3dirsearch.py-u<URL>-e<EXTENSI

  • java中重定向和转发的区别_java中转发和重定向的使用区别

    java中重定向和转发的区别_java中转发和重定向的使用区别java重定向和转发的区别response.sendredirect("http://www.foo.com/path/error.html");重定向和转发有一个重要的不同:当使用转发时,JSP容器将使用一个内部的方法来调用目标页面,新的页面继续处理同一个请求,而浏览器将不会知道这个过程。与之相反,重定向方式的含义是第一个页面通知浏览器发送一个新的页面请求。因为,当你使用重定向时,浏览器中所…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号