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.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值