9

我有 Java 知识,最近几天一直在学习 C#。现在我遇到了“virtual”关键字,正如此链接所建议的那样,它用于允许在子类中覆盖相应的方法、属性等。现在我认为即使不使用“virtual”关键字,我们也可以覆盖方法。那为什么有必要呢?

4

5 回答 5

14

virtual如果您真的想要override子类中的方法,则需要关键字。否则,基本实现将被新实现隐藏,就像您使用new关键字声明它一样。

通过“覆盖”它们而不声明基方法来隐藏方法virtual会使您没有多态性,这意味着:如果您将专用版本“转换”为“基”版本并调用方法,则始终将使用基类实现代替被覆盖的版本 - 这不是你所期望的。

例子:

class A
{
    public void Show() { Console.WriteLine("A"); }
}

class B : A
{
    public void Show() { Console.WriteLine("B"); }
}

A a = new A();
B b = new B();

a.Show(); // "A"
b.Show(); // "B"

A a1 = b;
a1.Show(); // "A"!!!
于 2012-12-13T09:35:54.453 回答
7

virtual是一种定义方法具有默认实现的方式,但该实现可以在子类中被覆盖。除了使用 virtual 之外,您不能在不使用new关键字的情况下直接覆盖方法(这通常是不好的做法)。

实现的一个很好的例子virtualToString()方法。C# 中的每个对象都保证能够调用ToString(),因为每个对象都继承自System.Object包含虚方法的基类ToString()。然而,派生类可以覆盖它,并提供它们自己的实现,这可能对对象的用户更有用。

更新:我最近写了一篇博文,深入探讨了这个话题。在这里查看

于 2012-12-13T09:35:07.483 回答
2

现在我认为即使不使用“virtual”关键字,我们也可以覆盖方法。

不,你不能。与 Java 不同,在 C# 中成员默认是密封的,virtual除非您使用关键字标记它们,否则您无法覆盖它们。

于 2012-12-13T09:34:51.173 回答
1

看看这个例子:

    void Main()
    {
        var o1 = new S();
        Console.WriteLine(((B)o1).m1());    
    }

    public class B
    {
        public virtual string m1() {
            return "m1";
        }
    }

    public class S : B
    {
        override public string m1() {
            return "overridden m1";
        }
    }

在此示例中,子类S被实例化并分配给对象变量o1。在Console.WriteLine语句的参数中,它被强制转换为基类B,然后m1调用方法。因为我们virtual在基类Boverride子类中使用过S,所以我们得到

被覆盖的 m1

作为输出。如果您在in和子类virtual的方法声明中删除,那么您将得到m1BoverrideS

米1

作为输出,这意味着强制转换也具有使用m1基类中方法的原始声明的效果B

注意如果您new在 subclass 中使用关键字S,例如

         new public string m1() {
            return "overridden m1";
        }

假设virtual基类中的关键字B不存在,您将获得输出

米1

也是。如果您不将其转换为B,则将使用新方法。这称为遮蔽(或隐藏)方法(基类的原始方法)。

概括:

  • 要覆盖一个方法,如果您强制转换为基类也应该有效,请在基类和子类中使用virtual关键字。override

  • 如果您打算覆盖仅应在子类中处于活动状态的方法,请new在子类方法声明中使用关键字。正如您所看到的,没有它它也可以工作,但如果它在那里更好,所以每个人都知道这是该方法的新版本。

于 2012-12-13T09:59:51.203 回答
0

如果派生类被实例化为基类,virtual / override 将允许派生类覆盖基函数。例子:

      class A
      {
         public virtual void Show() { Console.WriteLine("A"); }
      }

      class B : A
      {
         public override void Show() { Console.WriteLine("B"); }
      }


         A a = new A();
         B b = new B();

         a.Show(); 
         b.Show(); 

         A a1 = b;
         a1.Show();  // here is the test!!!

         B b1 = new B();
         b.Show();  

With virtual / override :
A
B
B
B

After removing virtual / override keywords (or simply removing override):
A
B
A
B
于 2021-05-20T20:48:53.307 回答