简体   繁体   中英

Derived from a base class that implements an interface

I get from Effective C# Item 23 that the following code should print: MyDerivedMessage

namespace ConsoleApplication1
{

    interface IMsg
    {
        void message();
    }

    public class MyMessage : IMsg
    {
        public void message()
        {
            Console.WriteLine("MyMessage");
        }
    }

    public class MyDerivedMessage : MyMessage
    {
        public new void message()
        {
            Console.WriteLine("MyDerivedMessage");
        }
    }

    class Test
    {

        static void Main()
        {
            MyDerivedMessage mdm = new MyDerivedMessage();
            IMsg im = mdm as IMsg;
            im.message();
        }
    }
}

Book:

public class MyDerivedClass : MyClass
{
    public new void Message()
    {
        Console.WriteLine("MyDerivedClass");
    }
}

The addition of the IMsg keyword changes the behavior of your derived class so that IMsg.Message() now uses the derived class version:

MyDerivedClass d = new MyDerivedClass();
d.Message(); // prints "MyDerivedClass".
IMsg m = d as IMsg;
m.Message(); // prints " MyDerivedClass "

How come I still get MyMessage printed after I add "new" to MyDerivedMessage::message() ?

You are hiding (or shadowing) the method rather than overriding it. This means that you will only call the method on the derived class when you access it from a variable declared to be that class (or more derived).

Note that this is the default on non-virtual methods, so adding "new" is just being more explicit.

If you don't want this behavior, you need to make the message method virtual in your base class, and override it in your derived class.

See also the documentation on new Modifier

It seems like maybe the book has some errata, but your MyDerivedMessage class would also need to implement IMsg. If this does not occur, then the cast to IMsg will only see MyMessage as having the Message() method when im.message() is called because of the chain created between the Interface and MyDerivedMessage.

MyDerivedMessage is-a MyMessage MyMessage is-a IMsg MyDerivedMessage NOT is-a IMsg

public class MyDerivedMessage : MyMessage, IMsg
{ 
    public new void message() 
    { 
        Console.WriteLine("MyDerivedMessage"); 
    } 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM