今天看了一道面试题,自己动手做了下,发现还是非常有趣的:
题目如下:
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 就可以了!