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"!!!
virtual是一种定义方法 * 具有 * 默认实现,但该实现可以在子类中被覆盖的方法。除了使用virtual之外,您无法在不使用new保留字的情况下直接覆写方法(这通常是不好的作法)。 实现virtual的一个很好的例子是ToString()方法。C#中的每个对象都保证能够调用ToString(),因为每个对象都继承自System.Object基类,该类包含一个虚方法ToString()。然而,衍生类别可以覆写这个,并提供自己的实作,这可能对对象的使用者更有用。 更新:我最近写了一篇博客文章,深入地探讨了这个主题。Check it out here的数据。
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)";
}
}
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
5条答案
按热度按时间m3eecexj1#
如果你真的想在子类中
override
方法,你需要virtual
关键字。否则,基本实现将被新实现隐藏,就像您使用new
关键字声明它一样。通过“覆盖”方法隐藏它们而不声明基本方法
virtual
使您没有多态性,这意味着:如果你把一个特殊化的版本“强制转换”到“基本”版本并调用一个方法,那么总是会使用基类的实现而不是被覆盖的版本--这不是你所期望的。范例:
字符串
mm5n2pyu2#
virtual
是一种定义方法 * 具有 * 默认实现,但该实现可以在子类中被覆盖的方法。除了使用virtual之外,您无法在不使用new
保留字的情况下直接覆写方法(这通常是不好的作法)。实现
virtual
的一个很好的例子是ToString()
方法。C#中的每个对象都保证能够调用ToString()
,因为每个对象都继承自System.Object
基类,该类包含一个虚方法ToString()
。然而,衍生类别可以覆写这个,并提供自己的实作,这可能对对象的使用者更有用。更新:我最近写了一篇博客文章,深入地探讨了这个主题。Check it out here的数据。
lo8azlld3#
现在我认为我们可以覆盖方法,即使不使用“virtual”关键字。
不,你不能。与Java相反,在C#中,成员是默认密封的,除非使用
virtual
关键字标记,否则无法覆盖它们。wvmv3b1j4#
看看这个例子:
字符串
在这个例子中,子类
Sub
被示例化并被分配给对象变量obj1
。在Console.WriteLine
语句的参数中,它被转换为基类Base
,然后调用方法method1
。因为我们在基类Base
中使用了virtual
,在子类Sub
中使用了override
,所以得到重写的方法1(来自Sub)
作为输出。
如果在
Base
中删除method1
的方法声明中的virtual
,并在子类Sub
的方法中删除override
,则会得到方法1(来自Base)
作为输出,这意味着强制转换还具有使用基类
Base
中方法method1
的原始声明的效果。注意如果在子类
Sub
中使用new
关键字,例如型
假设基类
Base
中的virtual
关键字不存在,您将得到输出方法1(来自Base)
如果你不把它转换为
Base
(并保持类型为Sub
),那么将使用新的method1
,这意味着它只属于声明它的类Sub
-同时从Base
类隐藏该方法的原始声明。这被称为 shadowing(或 hiding)一个方法。摘要:
virtual
关键字,在子类中使用override
关键字。new
关键字。正如你所看到的,它也可以在没有它的情况下工作,但是如果它在那里,那么每个人都知道这是一个新版本的方法,那就更好了。vs3odd8k5#
如果派生类被示例化为基类,则virtual / override将允许派生类重写基类函数。范例:
字符串