C#基类构造器调用虚方法
今天又翻出了Don Box的《Essential .Net》,又看到了当初曾经反复琢磨的虚方法分派的问题。在.net中,如果基类的构造器中调用了一个虚方法,它并不是直接调用基类中的虚方法,而是在子类中不存在override版本的时候才调用基类的虚方法,如果子类中有override版,那么就调用子类的方法。可以看个小例子,感觉下这种调用方式
public class Fruit
{
public Fruit()
{
WriteFruitName();
}
public virtual void WriteFruitName()
{
Console.WriteLine("Fruit's WriteFruitName()");
}
}
public class Banana : Fruit
{
public override void WriteFruitName()
{
Console.WriteLine("Banana's WriteFruitName()");
}
}
class Program
{
static void Main(string[] args)
{
Banana b = new Banana();
Console.ReadLine();
}
}
}
此方法执行后的结果是:Banana's WriteFruitName();因为Banana继承自Fruit,所以new Banana()首先调用基类的构造方法Fruit(),但是在基类构造方法内又调用了虚方法WriteFruitName,当程序执行到此次时,会在Banana的方法表中查找是否有方法WriteFruitName的override版,如果有则调用,没有就调用基类的虚方法。
下面看个略微深入点示例,道理都一样的,在方法中增加一名称属性,
public class Fruit
{
public Fruit()
{
FruitName = "Fruit";
WriteFruitName();
}
public virtual void WriteFruitName()
{
Console.WriteLine("Fruit's WriteFruitName(),The Name Is " + FruitName);
}
protected string FruitName{ get; set; }
}
public class Banana : Fruit
{
public Banana()
{
FruitName = "Banana";
}
public override void WriteFruitName()
{
Console.WriteLine("Banana's WriteFruitName(),The Name Is " + FruitName);
}
}
class Program
{
static void Main(string[] args)
{
Banana b = new Banana();
Console.ReadLine();
}
}
这次方法的执行结果是:Banana's WriteFruitName(),The Name Is Fruit。原因就是调用虚方法时,发现子类覆载了该方法,所以调用Banana类的WriteFruitName,但此时Banana类的构造器还没被执行,也就是说FruitName属性在Banana类中还没被赋值呢,而基类的构造器给它赋值为Fruit。这种方式仅供欣赏,实际生产中基本不这样用。