根据我的理解,virtual
关键字允许您使用基类'方法,override
允许您在继承自基类的类中覆盖它。我的困惑是我刚刚测试了在基类的方法定义中没有使用virtual关键字,并且在派生类中没有包含该方法,我仍然可以调用基类的方法(它出现在intellisense并运行) 。另外,我知道如果我想为我的派生类使用相同方法的新方法定义,我可以使用new关键字..
我可能错过了一个关键点,但这是我理解它的方式,这就是为什么我对虚拟和覆盖的目的感到困惑
答案 0 :(得分:3)
我认为一个例子有助于理解最多。请考虑以下事项:
class Base {
public virtual void f() { Console.WriteLine("Virtual Base"); }
}
class Override : Base {
public override void f() { Console.WriteLine("Overridden derived"); }
}
class New : Base {
public new void f() { Console.WriteLine("New derived"); }
}
现在,如果您有一个实际类型Derived
但静态类型Base
的对象,则调用f()
仍会输出“Overridden Derived”:
Base obj = new Override();
obj.f(); // Overridden derived
使用new
关键字,告诉运行时停止从该类开始查找具有该名称的方法:
Base obj = new New();
obj.f(); // Virtual Base
与至少在f()
类型上调用New
相反:
New obj = new New();
obj.f(); // New derived
答案 1 :(得分:2)
我的困惑是我刚刚测试过没有使用虚拟关键字 基类的方法定义,而不包括该方法 派生类,我仍然能够调用基类的方法(它 出现在intellisense并且跑了。)
这是预期的行为。
Virtual允许你override一个在基类中定义的方法,换句话说,扩展派生类中方法的实现。
新关键字与覆盖一个can be found on MSDN here之间的差异。
如果您能够在派生类中调用基类方法,则access modifiers(private,public,protected)会受到影响。
答案 2 :(得分:0)
Virtual允许您覆盖基类方法。你仍然可以在没有它的情况下调用该方法,但如果没有它,将无法覆盖该方法。
抱歉,我忘记提及多态性了。因此,如果你有一个定义方法的基类,你可以做这样的事情。
以下代码段将从B
打印public class A
{
virtual void foo
{
Console.WriteLine("From A");
}
}
public class B : A
{
override void foo()
{
Console.WriteLine("From B");
}
}
static void Main(string[] args)
{
A testA = new B();
a.foo();
}
答案 3 :(得分:0)
要覆盖基类中的方法,必须将覆盖的方法标记为虚拟 - 使用覆盖关键字覆盖方法。
新方法的上下文略有不同。它允许您在子类中添加一个方法,该方法的名称与基类中的方法相同。调用哪个方法取决于您用来访问该方法的引用。
您可以访问基类中实现的任何方法(受访问修饰符限制),无论它们是否标记为虚拟。
答案 4 :(得分:0)
当您将方法标记为虚拟或抽象时,运行时类型检查用于确定要调用的方法的实际实现:它检查实现/覆盖虚方法的“派生类型最多”,并调用那个实现。普通方法不需要运行时类型检查。
因此,虚拟和非虚拟之间的区别会对代码的语义产生有意义的影响,尤其是对于公共API。如果你看到这个:
class A { void foo(); virtual void bar(); }
...
A myObject = getSomeObject();
myObject.foo();
myObject.bar();
您可以确定调用的foo
的实现是在类A
中声明的实现。这是因为只使用编译时类型检查来确定要调用的方法。但是,调用的bar
的具体实现可能是A
的某个子类中的实现,具体取决于myObject
的运行时类型。
更多信息:http://msdn.microsoft.com/en-us/library/aa645767(v=vs.71).aspx