从derived而不是base调用的虚方法

时间:2013-02-28 16:42:15

标签: c# virtual base derived-class

有人可以向我解释为什么在将类转换为基类时调用被重写的方法:

    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或其他类)

2 个答案:

答案 0 :(得分:9)

根据对象的执行时间类型选择方法实现。这是其中很重要的一部分。任何人都可以使用:

public void Foo(Base b)
{
    b.VirtualMethod();
}

...并且不需要知道或关心执行类型是什么,因为多态性会处理它。

  

我知道我可以通过调用base.VirtualMethod()从派生中调用Base的虚方法,但是我可以从外面调用它吗?

否(至少,并非没有一些可怕的hackery非虚拟地调用虚拟方法),这是封装的故意部分。覆盖实现已经有效地替换了该对象的原始实现。

答案 1 :(得分:2)

如果要访问基本实现,则不应使用override,应使用new。覆盖覆盖任何父实现,新“隐藏”父实现,以便您可以通过强制转换为父对象然后调用该方法来访问实现。

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");
        }
    }
}

这将输出:

  

Overriden方法
  基本虚拟方法