estimpson
estimpson

Reputation: 113

Why is base class method called instead of derived class method?

Expecting "Hello from the derived." but getting "Hello from the base.".

class Program
{
    interface IBase
    {
        void Method();
    }

    public class Base: IBase
    {
        public virtual void Method()
        {
            Console.WriteLine("Hello from the base.");
        }
    }

    public class Derived : Base
    {
        public virtual new void Method()
        {
            Console.WriteLine("Hello from the derived.");
        }
    }

    static void Main(string[] args)
    {
        IBase x = new Derived();
        x.Method();
    }
}

So why isn't the derived class's method called. And more importantly, how can I get the derived classes method to get called without casting x to the Derived type?

In my actual application, IBase has several other related methods and Derived only replaces two of the methods in IBase.

Upvotes: 9

Views: 7688

Answers (5)

Servy
Servy

Reputation: 203827

When you use the new modifier you are specifically saying that the method is not part of the virtual dispatch chain for that hierarchy, so calling the method by the same name in the base class will not result in redirection to the child class. If you mark the method with override instead of new then you will see the virtual dispatch that you are expecting to see.

You will also need to remove virtual from the derived class's method as you cannot mark an override method as virtual (it already is).

If you really don't want to override the method then it may be more appropriate, in your situation, to not use inheritance at all. You may simply want to use interfaces exclusively:

public interface IFoo
{
    void Foo();
}

public class A : IFoo
{
    public void Foo()
    {
        Console.WriteLine("I am A, hear me roar!");
    }
}

public class B : IFoo
{
    public void Foo()
    {
        Console.WriteLine("I am B, hear me roar!");
    }
}

private static void Main(string[] args)
{
    IFoo foo = new A();
    foo.Foo();

    foo = new B();
    foo.Foo();

    Console.WriteLine();
    Console.WriteLine("Press any key to exit . . .");
    Console.ReadKey(true);
}

Upvotes: 12

Louis Kottmann
Louis Kottmann

Reputation: 16628

The new'd Method in Derived only exists in a Derived instance, where it effectively hides the base implementation.

But IBase type only knows the Base's implementation, so it calls that.

To answer your question, to call the derived's implementation you'd do:

Derived d = new Derived();
d.Method();
((IBase)d).Method();

//Prints:
//Hello from the derived.
//Hello from the base.

Upvotes: -1

emartel
emartel

Reputation: 7773

Use the override keyword instead of virtual new in your child class.

Therefore, your code should look like:

class Program
{
    interface IBase
    {
        void Method();
    }

    public class Base: IBase
    {
        public virtual void Method()
        {
            Console.WriteLine("Hello from the base.");
        }
    }

    public class Derived : Base
    {
        public override void Method() // The magic happens here!
        {
            Console.WriteLine("Hello from the derived.");
        }
    }

    static void Main(string[] args)
    {
        IBase x = new Derived();
        x.Method();
    }
}

As described here, the new keyword is used to hide the parent method, which is not what you're looking for.

Upvotes: 2

Knaģis
Knaģis

Reputation: 21485

new keyword creates a new method and says that the base method is hidden. But it is only for consumers of your derived class, since the base class code does not know anything about it.

override keyword overrides the base class implementation with a new one.

class Program
{
    interface IBase
    {
        void Method();
    }

    public class Base: IBase
    {
        public virtual void Method()
        {
            Console.WriteLine("Hello from the base.");
        }
    }

    public class Derived : Base
    {
        // the next line was changed.
        public override void Method()
        {
            Console.WriteLine("Hello from the derived.");

            // note that if you want to call the original implementation, you do it like this:
            base.Method();
        }
    }

    static void Main(string[] args)
    {
        Base x = new Derived();
        x.Method();
    }
}

Upvotes: 1

Jerad Rose
Jerad Rose

Reputation: 15503

This is basic polymorphism at work.

For the behavior you're looking for, you would need to set your derived method to override the inherited method:

public class Derived : Base
{
    public override void Method()
    {
        Console.WriteLine("Hello from the derived.");
    }
}

Upvotes: 3

Related Questions