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则会新开一个虚方法槽。
本例分析:编译器看到是隐式实现的接口,就什么也不考虑,使用原来匹配的所有方法,而不重新匹配方法。