从一道面试题看继承对象间在实例化时的顺序

今天看了一道面试题,自己动手做了下,发现还是非常有趣的:

题目如下:

using System;

class A

{

public A()

{

PrintFields();

}

public virtual void PrintFields(){}

}

class B:A

{

int x=1;

int y;

public B()

{

y=-1;

}

public override void PrintFields()

{

Console.WriteLine("x={0},y={1}",x,y);

}

当使用new B()创建B的实例时,产生什么输出?

我特意在VS上试了下,结果真的很有趣,你有想到答案么?

我稍微修改了下(加了两句输出),如下:

class A
        {
             public A()
             {
                 Console.WriteLine("a");
                 PrintFields();
             }

            public virtual void PrintFields(){}
        }

        class B:A
        {
            int x = 1;
            int y;
             public B()
             {
                 Console.WriteLine("b");
                 y = -1;
             }
             public override void PrintFields()
             {
                 Console.WriteLine("x={0},y={1}",x,y);
             }
        }

运行后,输出结果如下:

a
x=1,y=0
b

从上结果可看出,在实例化B时,先实例化父类A,但在A的构造函数中,却可以调用B中override的PrintFields()方法。但为何在B未实例化之前,它的方法可以被调用呢?

在网上查考了下,原来每个类有一个固定的初始化顺序:

依次如下:

1: 子类静态变量

2: 子类静态构造函数

3: 子类非静态变量

4: 父类静态变量

5: 父类静态构造函数

6: 父类非静态变量

7: 父类构造函数

8: 子类构造函数

从这里,或许 大家可以初见端倪了吧!原来非静态的构造函数 都是最后被初始化的!

那如果 父类的 虚方法 有实现的话,结果会怎么样呢?

再修改下代码,如下:

class A
        {
             public A()
             {
                 Console.WriteLine("a");
                 PrintFields();
             }

            public virtual void PrintFields()
            {
                Console.WriteLine("parant");
            }
        }

        class B:A
        {
            int x = 1;
            int y;
             public B()
             {
                 Console.WriteLine("b");
                 y = -1;
             }
             public override void PrintFields()
             {
                 Console.WriteLine("x={0},y={1}",x,y);
             }
        }

结果看输出 依然与上次无异:

a
x=1,y=0
b

说明父类还是会去调用子类重写过的方法的,和自身有实现没有任何关系。如果不想影响父类中的实现,自己这里也需要实现,不要override,用new 就可以了!

posted @ 2013-02-28 18:08  davidlovelife  阅读(224)  评论(0编辑  收藏  举报