我对java有所了解,过去几天一直在学习c#。现在我遇到了“虚拟”关键字,正如this link所建议的那样,用于允许在子类中覆盖相应的方法,属性等。现在我认为即使不使用“virtual”关键字也可以覆盖方法。那为什么有必要呢?
答案 0 :(得分:12)
如果您真的想要子类中的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"!!!
答案 1 :(得分:7)
virtual
是一种定义方法具有默认实现的方法,但该实现可以在子类中重写。除了使用虚拟之外,您无法在不使用new
关键字的情况下直接覆盖方法(这通常是不好的做法)。
virtual
方法的一个很好的示例是ToString()
方法。 C#中的每个对象都保证能够调用ToString()
,因为每个对象都继承自基类System.Object
类,其中包含虚方法ToString()
。派生类可以覆盖它,并提供它们自己的实现,这可能对对象的用户更有用。
更新:我最近写了一篇博文,深入探讨了这个主题。 Check it out here
答案 2 :(得分:2)
不,你不能。与Java相反,C#成员默认密封除非您使用现在我认为即使不使用“virtual”关键字也可以覆盖方法。
virtual
关键字标记,否则无法覆盖它们。
答案 3 :(得分: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
中使用了B
而在子类override
中使用了S
,所以我们得到了
重写了m1
作为输出。如果您删除了virtual
中的m1
和B
子类override
的方法声明中的S
,那么您将获得
M1
作为输出,这意味着强制转换还具有使用基类m1
中方法B
的原始声明的效果。
N.B。如果您在子类new
中使用S
关键字,例如
new public string m1() {
return "overridden m1";
}
假设基类virtual
中的B
关键字不存在,那么您将获得输出
M1
也是。如果您不将其强制转换为B
,则会使用新方法。这称为 shadowing (或隐藏)方法(基类的原始方法)。
摘要:
要覆盖一个方法,该方法在强制转换为基类时也应该有效,请在基类中使用virtual
关键字,在子类中使用override
。
如果要覆盖仅在子类中处于活动状态的方法,请在子类方法声明中使用new
关键字。正如你所看到的那样它也可以没有它,但如果它存在则更好,所以每个人都知道这是该方法的新版本。
答案 4 :(得分: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