无法在C#中使用相同方法的虚拟和覆盖

Fra*_*gio 17 c# polymorphism

显然你不能将virtual修饰符与修饰符一起使用override.

virtual - 可以覆盖的方法

override - 一个覆盖其父类中同名方法的方法

这让我相信,如果我覆盖子类中的方法,如果该子项有子,则无法再次覆盖该方法.

并且可以肯定地说,如果你在方法声明中放入override,virtual你将在C#中得到一个编译错误.

但是我无法理解为什么我在下面编写的代码按照它的方式工作

using System;
public class DrawingObject
{
public virtual void Draw()
{
    Console.WriteLine("Drawing Object");
}
}
public class DrawDemo
{
     public static int Main()
     {
          DrawingObject[] dObj = new DrawingObject[3];


          dObj[0] = new DrawingObject();
           dObj[1] = new Line();
           dObj[2] = new LittleLine();

           foreach (DrawingObject drawObj in dObj)
           {
                drawObj.Draw();
           }
            Console.Read();
           return 0;
       }
  }
 public class Line : DrawingObject
 {
       public override void Draw()
       {// the method above me is in fact virtual because LittleLine overid it?
               Console.WriteLine("I'm a Line.");
       }
  }
  public class LittleLine : Line
  {
       public override void Draw()
       {
              Console.WriteLine("I'm a Little Line.");
         }
    }
Run Code Online (Sandbox Code Playgroud)

这是输出:

绘图对象

我是一条线.

我是一条小线.

因此,绘制方法Line看起来好像被覆盖了LittleLine.这个代码实际上没有覆盖它,还是编译器正在做其他一些技巧?还是我不理解的情况下virtualoverride

era*_*ran 27

您可以将某个方法声明为virtual仅一次,但您可以override根据需要多次声明 - 覆盖不是最终的,并且它不会限制从第一个重写类继承的类.最终将执行的方法是覆盖虚方法的最后一个方法.所以你的代码确实按预期运行.

关于覆盖,C#非常冗长 - 你有比C++或Java更多的说明符.让程序员指定确切的意图是这样的:

  • virtual用来指定可以由子类重写的方法.
  • override用来指定覆盖一个您知道是虚拟的方法(如果不是,编译器将报告错误).
  • sealed用来防止进一步覆盖.
  • 而你new用来隐藏而不是覆盖.

这可能令人困惑,有时也很烦人,但它可以确保您真正知道自己在做什么,并且可以让您的意图自我记录.


Jon*_*eet 5

所以显然你不能将 virtual 修饰符与 override 修饰符一起使用。

的确。该方法保持虚拟状态,除非您使用也声明为 的方法覆盖它sealed。(只有当您重写某些内容时,才能对sealed方法使用修改。)来自 C# 4 规范的第 10.6.5 节:

当实例方法声明包含密封修饰符时,该方法被称为密封方法。如果实例方法声明包含 seal 修饰符,则它还必须包含 override 修饰符。使用 seal 修饰符可防止派生类进一步重写该方法。