我的代码如下,很简单,Chicken继承于Bird,Bird继承于Animal;
三个类里面的Eat方法都是非虚方法,根据我所了解的继承和方法表的知识,使用了new关键字,子类隐藏了父类的同名方法,这一点在下面的方法表中也确实如此,可问题时,对象调用时的结果我不能够理解,请高人指点一二,谢谢了。
结果输出:
Chicken always eat.
Bird always eat.
Animal always eat.
程序代码:
public class Animal
{
public void Eat()
{
Console.WriteLine("Animal always eat.");
}
}
public class Bird : Animal
{
public void Eat()
{
Console.WriteLine("Bird always eat.");
}
}
public class Chicken : Bird
{
public new void Eat()
{
Console.WriteLine("Chicken always eat.");
}
}
public class TestInheritance
{
public static void Main()
{
Chicken chicken = new Chicken();
Bird bird = new Chicken();
Animal animal = new Chicken();
chicken.Eat();
bird.Eat();
animal.Eat();
//animal = new Bird();
//animal.Eat();
Console.Read();
}
}
Chicken的方法表:
0:003> !dumpmt -md 00993188
EEClass: 0099145c
Module: 00992c3c
Name: Chicken
mdToken: 02000004 (F:\csc\demo8.exe)
BaseSize: 0xc
ComponentSize: 0x0
Number of IFaces in IFaceMap: 0
Slots in VTable: 6
--------------------------------------
MethodDesc Table
Entry MethodDesc JIT Name
79352e40 791382c8 PreJIT System.Object.ToString()
79351bc0 791382d0 PreJIT System.Object.Equals(System.Object)
79351bb0 791382e8 PreJIT System.Object.GetHashCode()
793484c0 791382f0 PreJIT System.Object.Finalize()
00cd0198 00993178 JIT Chicken.Eat()
00cd0108 00993180 JIT Chicken..ctor()
你既然多知道覆盖了 父类的方法 那怎么还会对结果长生疑问呢 ???
问题是:Eat是被new了的,被new后的定义只有在new的类以及其派生类里有效果,而且当被再次new后,会递归的使用这个策略。
定义被new后,在对象的内存空间里,就有了一个新的地址分配。所以,在调用的时候,会出现你的问题。
Chicken chicken = new Chicken();
chicken.Eat();
(chicken as Bird).Eat();
(chicken as Animal).Eat();
(chicken as Bird as Animal).Eat();
都会是这个情状。
当我们调用一个对象的属性的时候,我们首先使用的是这个对象变量定义的类型,然后去这个类型里查找要调用的目标内容。如果查找的时候,发现这个目标是可重载的并且被对象的实际实现重载了,则使用重载后的目标,否则,无论实际使用的对象是否有使用new定义,都使用对象定义类型里定义的目标。
即:
Bird bird = new Chicken();
虽然bird的实现是一个Chichen,但bird这个变量的类型是Bird,因此,在调用Eat这个方法的时候,使用Bird里定义的Eat这个方法。
如果,你使用可变变量类型,结果就会如你所期望的:
var chicken = new Chicken();
var bird = new Chicken();
var animal = new Chicken();
那么,他们的Eat输出都是Chicken里定义的。
特别的,即便你定义成:
var bird2 = new Chicken() as Bird;
输出的还是Chicken的内容。
另外一个定义:
Bird bird = new Chicken();
var animal = bird as Animal;
那么:
bird.Eat()的输出是BIRD
animal.Eat()的输出又变成了Chicken。