首页 新闻 会员 周边 捐助

请教关于继承后方法的执行问题

0
悬赏园豆:50 [待解决问题] 解决于 2011-03-31 12:43

我的代码如下,很简单,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()

电脑混混的主页 电脑混混 | 初学一级 | 园豆:6
提问于:2011-03-16 12:43
< > 字节跳动旗下AI助手豆包
分享
所有回答(2)
0

你既然多知道覆盖了 父类的方法 那怎么还会对结果长生疑问呢  ???

小w威 | 园豆:37 (初学一级) | 2011-03-16 13:55
Chicken的方法表只有Chicken的Eat,为何bird和animal会输出Bird和Animal,不是很理解
支持(0) 反对(0) 电脑混混 | 园豆:6 (初学一级) | 2011-03-16 14:10
0

问题是: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。

无之无 | 园豆:5095 (大侠五级) | 2011-11-11 09:23
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册
Top