派生类的接口实现 [英] Interface implementation with derived class

查看:94
本文介绍了派生类的接口实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

public class Program
    {
        static void Main(string[] args)
        {
            Document theNote = new Note("Test Note");
            IStorable isNote = theNote as IStorable;

            if (isNote != null)
            {
                isNote.Read();
                isNote.Write();
            }

            Console.WriteLine("\n");

            theNote.Read();
            theNote.Write();

            Console.WriteLine("\n");

            Note note2 = new Note("Second Note");
            IStorable isNote2 = note2 as IStorable;

            if (isNote2 != null)
            {
                isNote2.Read();
                isNote2.Write();//see this output            
            }

            Console.WriteLine("\n");

            note2.Read();
            note2.Write();

        }
    }

    interface IStorable
    {
        void Read();
        void Write();
    }

    public class Document : IStorable
    {
        public Document(string s)
        {
            Console.WriteLine("creating document with: {0}", s);
        }

        public virtual void Read()
        {
            Console.WriteLine("Document Read method for IStorable");
        }
        public void Write()
        {
            Console.WriteLine("Document Write method for IStorable");
        }
    }

    public class Note : Document
    { 
        public Note(string s) : base(s)
        {
           Console.WriteLine("creating Note with: {0}", s);
        }
        public override void Read()
        {
            Console.WriteLine("Overriding Read method for Note");
        }
        public void Write()
        {
            Console.WriteLine("My Write method for Note");
        }
    }



为什么isNote2.Write()打印出Document.Write()而不是Note.Write().

由于这是一个类型为Note的对象,该对象被强制转换为接口类型的isNote2,因此生成的isNOte2.write()应该实现NOte.write()而不是document.write().



Why does isNote2.Write() print out the Document.Write() and not the Note.Write().

Since this is a object of type Note, which is casted to isNote2 which is a interface type, the resulting isNOte2.write() should implement the NOte.write() and not document.write().

推荐答案

这是因为您没有将第一个方法Writevirtual以及第二个方法标记为override.如果这样做,它将按预期工作.

您还忽略了编译器警告,该警告告诉您Node.Write隐藏了继承的方法Write.如果不忽略它,您可能会得到线索并自己理解问题.

现在,我认为您应该得到它.问题本身是固定的,但是我是否必须向您解释问题中显示的代码的行为?从上面的段落和上面提到的警告中应该显而易见.



您真的了解通过虚拟机制和虚拟方法表进行的动态调度是如何工作的吗?我希望你会.接口的存在稍微掩盖了这张图片,但实际上没有任何区别.

顺便说一句,我建议您不要使用显式接口实现语法来减少混乱的机会.考虑将代码更改为此:

This is because you did not mark first method Write and virtual and the second one as override. If you did, it would work as you expected.

You also ignored compiler warning which told you that Node.Write hides the inherited method Write. If you did not ignore it, you would probably get the clue and understood the problem by yourself.

Now, I think you should get it. The problem itself is fixed, but do I have to explain you the behavior of the code you''ve shown in your question? It should be apparent from the above paragraph and the warning mentioned above.



And do you really understand how dynamic dispatch via virtual mechanism and virtual method table really works? I hope you do. The presence of interfaces masks this picture a bit, but it makes no difference, in fact.

By the way, I would advise you do use explicit interface implementation syntax to reduce the chance of confusion. Consider changing the code to this:

public class Document : IStorable
{
    public Document(string s) { /* ... */ }
    void IStorable.Read() { ImplementRead(); } //no access specifier allowed!
    void IStorable.Write() { ImplementWrite(); } //no access specifier allowed!
    internal protected virtual void ImplementRead() { /* ... */ }
    internal protected virtual void ImplementWrite() { /* ... */ }
}



没有什么是公共的,所有都是显式的,虚拟方法与接口实现是分开的.显式语法还有其他好处.

-SA



Nothing is public, all is explicit, virtual methods are separated from interface implementations. There are some other benefits of explicit syntax.

—SA


实际上,由于note.write()隐藏document.write(),因此对isnote2.write()的调用应调用write注释类而不是文档类中的方法....


as a mater of fact since note.write() hides document.write(), the call to isnote2.write() should invoke the write method in the note class and not the document class....


Note note2 = new Note("Second Note");//this is a note object and not a document 
            IStorable isNote2 = note2 as IStorable;//casting 
 
            if (isNote2 != null)
            {
                isNote2.Read();
                isNote2.Write();//why does it not print as note2.write() but print as theNote.Write()?            
            }


感谢您的解决方案SAKryukov ...我对C#完全陌生.找出答案,并希望与其他可能陷入困境的人分享...我还需要专家对此进行评论...

答:

1)
Thanks for your solution SAKryukov...I am totally new to C#...im from a C++ background....so im thinking that perspective...but I figured out the answer and would like to share with the rest who might stump into my difficulty...I also need the experts to comment on it...

Answer:

1)
Note note2 = new Note("Second Note");


2)

IStorable isNote2 = note2 as IStorable;//casting


3)

if (isNote2 != null)
            {
                isNote2.Read();
                isNote2.Write();
             }





1)创建一个Note对象,该对象本质上具有所有基类.
2)此强制转换使IStorable类型引用Note对象.
3)在Read()中,IStorable类型查看第一个派生类(文档类)并找到该方法.但是,由于它是虚拟的(以及虚拟查找的所有开销),因此它会找到Note类型的替代方法并进行打印.它对Write()的作用相同,但是由于Write()不是虚拟的,因此它打印文档类.因此,投射会导致自上而下的查找.





1) A Note object is created which by its nature has all the base class in it.
2) This casting makes a IStorable type refer to the Note object.
3) In the Read(), the IStorable type looks at the first derived class(the document class) and finds that method. However, since its virtual(and all the overheads of virtual look up)it finds the override method of Note type and prints that. It does the same for the Write() but since Write() is not virtual, it prints the document class. So casting causes the look up from top-down.


这篇关于派生类的接口实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆