Virtual method called from derived instead of base

2019-01-20 11:18发布

问题:

Can someone explain to me why is the overridden method being called when I cast the class into the base one:

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

I mean this code prints:

Overriden method

and not

Base virtual method

Its a run-time or compile-time future?

I know i can call the Base's virtual method from the derived by calling base.VirtualMethod() but can I call it from outside? (like from Main or some other class)

回答1:

The method implementation is chosen based on the execution-time type of the object. That's a large part of the point of it. Anyone can use:

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

... and not need to know or care what the execution type is, because polymorphism will take care of it.

I know i can call the Base's virtual method from the derived by calling base.VirtualMethod() but can I call it from outside?

No (at least, not without some horribly hackery to call the virtual method non-virtually), and that's a deliberate part of encapsulation. The overriding implementation has effectively replaced the original implementation for that object.



回答2:

If you want to access base implementation you should not use override, you should use new. Override overrides any parent implementation, new 'hides' the parent implementation so that you can access the implementation by casting as the parent object then invoking the method.

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

This will output:

Overriden method
Base virtual method