接口深度剖析(子类没有重新实现)


    interface IFather
    {
        void X();
        void Y();
        void Play();
        void Clear();
    }
   
    class B : IFather
    {
        public   void X()
        {
            Console.WriteLine("B::X()");
        }
        public void Y()
        {
            Console.WriteLine("B::Y()");
        }
        public void Play()
        {
            Console.WriteLine("B::Play()");
        }
        public void Clear()
        {
            Console.WriteLine("B::Clear()");
        }
    }
    class C : B
    {
        public new void Play()
        {//该方法虽然隐藏了基类中的方法,但是并非是虚的
            Console.WriteLine("C::Play()");
        }
        public new void Clear()
        {//该方法虽然隐藏了基类中的方法,但是并非是虚的
            Console.WriteLine("C::Clear()");
        }
    }

  
    class Program
    {
        static void Main(string[] args)
        {
            C c = new C();
            c.X();//cfather::x()
            c.Y();//cfather::y()
            c.Play();//cson::play()
            c.Clear();//cson::clear()
            IFather f = c;
            f.X();//cfather::x()
            f.Y();//cfather::y()
            f.Play();//cfather::play()
            f.Clear();//cfather::clear()
            Console.Read();
        }
    }

 

这里要深入理解接口中是怎样去找匹配的方法的

0 先判断接口是否要重新实现,如果不重新实现,则所有的都还是和父类的一样,如果是重新实现,则重新分配

 如果要重新实现则按一下步骤:

1 在实现接口的类中找本类对应的显示实现(IFather.X())如果找不到

2 在实现接口的类中找本类对应的virtual方法,如果找不到

3在实现接口的方法中找本类对应的公有非静态的方法,如果找到则将其虚化(public virtual seleaed)

       并将其放入虚函数表中,如果找不到

(注意:先找的都是本类的方法,即便是虚表都从子类拷贝过来了,但是还是得区分是本类自己的虚方法还是父类继承过来的虚方法)

4 到其直接基类中找对应的virtual方法,如果找不到

4则在该直接基类中找对应的公有非静态的方法,如果找到,本应该将其虚化,但是基类的方法,子类无权虚化,故在

  子类中自动生成一个该方法的显示实现,在显示实现的方法中去调用基类中刚刚找到的方法,如果没找到则继续按这个顺序递归到基类中,知道最后如果找不到则编译错误

注意:1 被虚化的方法是可以继承,但是不能override的了。

            2在类中,接口表的接口不仅有自己实现的接口,而且所有基类实现的接口都在该类的接口表中。

           3隐藏在虚方法和非虚方法之间也是可以的。非虚方法还是非虚方法,虚方法还是虚方法,在以上例子中,CFather中的play() ,clear() ,x(),y()都被虚化成了public virtual seleaed的,放在了虚方法表中了,在Cson中play() ,clear() ,只是new类以下,而其自身并不是virtual的,故在Cson中play() ,clear() 的两个方法放在了实方法中,如果在Cson中play() ,clear() 都标记成virtual则会新开一个虚方法槽。

本例分析:编译器看到是隐式实现的接口,就什么也不考虑,使用原来匹配的所有方法,而不重新匹配方法。

原文地址:https://www.cnblogs.com/qianyz/p/1839838.html