C# 从派生而不是基调用的虚拟方法
有人能向我解释一下,当我将类强制转换为基类时,为什么要调用重写的方法吗C# 从派生而不是基调用的虚拟方法,c#,virtual,base,derived-class,C#,Virtual,Base,Derived Class,有人能向我解释一下,当我将类强制转换为基类时,为什么要调用重写的方法吗 class Base { public virtual void VirtualMethod() { Console.WriteLine("Base virtual method"); } } sealed class Derived : Base { public override void V
class Base
{
public virtual void VirtualMethod()
{
Console.WriteLine("Base virtual method");
}
}
sealed class Derived : Base
{
public override void VirtualMethod()
{
Console.WriteLine("Overriden method");
}
}
static void Main(String[] args)
{
Derived d = new Derived();
((Base)d).VirtualMethod();
}
我的意思是这个代码打印:
Overriden method
而不是
Base virtual method
将来是运行时还是编译时
我知道我可以通过调用
Base.VirtualMethod()
从派生的调用Base的虚拟方法,但是我可以从外部调用它吗?(就像来自Main
或其他一些类)方法实现是基于对象的执行时间类型选择的。这是问题的一大部分。任何人都可以使用:
public void Foo(Base b)
{
b.VirtualMethod();
}
。。。而且不需要知道或关心执行类型是什么,因为多态性将处理它
我知道我可以通过调用Base.VirtualMethod()从派生的调用Base的虚方法,但是我可以从外部调用它吗
不(至少,没有一些骇人听闻的黑客以非虚拟方式调用虚拟方法),这是封装的一部分。覆盖实现已有效地替换了该对象的原始实现。如果要访问基本实现,则不应使用覆盖,应使用新实现。覆盖覆盖任何父实现,新的“隐藏”父实现,以便您可以通过强制转换为父对象然后调用该方法来访问该实现
internal class Program
{
private static void Main(string[] args)
{
Derived d = new Derived();
d.VirtualMethod();
((Base) d).VirtualMethod();
Console.ReadLine();
}
private class Base
{
public virtual void VirtualMethod()
{
Console.WriteLine("Base virtual method");
}
}
private sealed class Derived : Base
{
public new void VirtualMethod()
{
Console.WriteLine("Overriden method");
}
}
}
这将输出:
重写方法基本虚方法
请试着理解@Jon Skeet的回答。他完全正确。设计的原因是几十年的丰富经验和不断探索更好的代码编写方法。“暗箱操作”/“机械原因”在某种程度上是不相关的,因为所有支持OOP的语言和运行时都有相同的行为(至少在涉及虚拟方法时是如此),并且每种语言和运行时的实现都不同。关于第二个问题,请看:+1。注意,行为与C++相反,其中构造函数的虚调用将调用基类的实现。这两种行为都令人困惑,并可能带来令人惊讶的副作用,因此通常不建议从构造函数调用虚拟函数。