.net C#中的virtual关键字

xiozqbni  于 2023-08-08  发布在  .NET
关注(0)|答案(5)|浏览(121)

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

m3eecexj

m3eecexj1#

如果你真的想在子类中override方法,你需要virtual关键字。否则,基本实现将被新实现隐藏,就像您使用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"!!!

字符串

mm5n2pyu

mm5n2pyu2#

virtual是一种定义方法 * 具有 * 默认实现,但该实现可以在子类中被覆盖的方法。除了使用virtual之外,您无法在不使用new保留字的情况下直接覆写方法(这通常是不好的作法)。
实现virtual的一个很好的例子是ToString()方法。C#中的每个对象都保证能够调用ToString(),因为每个对象都继承自System.Object基类,该类包含一个虚方法ToString()。然而,衍生类别可以覆写这个,并提供自己的实作,这可能对对象的使用者更有用。
更新:我最近写了一篇博客文章,深入地探讨了这个主题。Check it out here的数据。

lo8azlld

lo8azlld3#

现在我认为我们可以覆盖方法,即使不使用“virtual”关键字。
不,你不能。与Java相反,在C#中,成员是默认密封的,除非使用virtual关键字标记,否则无法覆盖它们。

wvmv3b1j

wvmv3b1j4#

看看这个例子:

void Main()
{
    var obj1 = new Sub();
    Console.WriteLine(((Base)obj1).method1());
}

public class Base
{
    public virtual string method1()
    {
        return "method1 (from Base)";
    }
}

public class Sub : Base
{
    override public string method1()
    {
        return "overridden method1 (from Sub)";
    }
}

字符串
在这个例子中,子类Sub被示例化并被分配给对象变量obj1。在Console.WriteLine语句的参数中,它被转换为基类Base,然后调用方法method1。因为我们在基类Base中使用了virtual,在子类Sub中使用了override,所以得到
重写的方法1(来自Sub)
作为输出。
如果在Base中删除method1的方法声明中的virtual,并在子类Sub的方法中删除override,则会得到
方法1(来自Base)
作为输出,这意味着强制转换还具有使用基类Base中方法method1的原始声明的效果。

注意如果在子类Sub中使用new关键字,例如

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


假设基类Base中的virtual关键字不存在,您将得到输出
方法1(来自Base)
如果你不把它转换为Base(并保持类型为Sub),那么将使用新的method1,这意味着它只属于声明它的类Sub-同时从Base类隐藏该方法的原始声明。这被称为 shadowing(或 hiding)一个方法。

摘要:

  • 要重写一个方法,如果你强制转换到基类也应该有效,在基类中使用virtual关键字,在子类中使用override关键字。
  • 如果您打算重写该方法(该方法应仅在子类中处于活动状态),请在子类方法声明中使用new关键字。正如你所看到的,它也可以在没有它的情况下工作,但是如果它在那里,那么每个人都知道这是一个新版本的方法,那就更好了。
vs3odd8k

vs3odd8k5#

如果派生类被示例化为基类,则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

字符串

相关问题