类的构造函数

构造函数是类的特殊方法,在使用new关键字创建类对象时被间接的调用,和普通的方法不同的是,类的构造函数是没有返回值的,连一个void都没有,并且构造函数的名字和类名相同。

因为构造函数也是类的方法,所以构造函数也支持方法的重载。如果我们在定义一个类的时候没有显示的为它定义构造函数,C#将为我们提供一个默认的构造函数。默认的构造函数没有参数,它的访问权限是public的,它将确保类的所有字段数据都被设置为正确的默认值。

1 class Car
2 {
3   public string petName;
4   public int currSpeed;    
5 }

当创建一个Car的实例时,默认构造函数将被调用,并设置petName的值为null,currSpeed的值为0.

1 Car car = new Car();

当然,默认构造函数它所能作的事情是有限的,这时我们可以重新定义类的构造函数,从而达到我们想要的目的。如下为Car类自定义了一个构造函数:

 1 class Car
 2 {
 3   public string petName;
 4   public int currSpeed;
 5 
 6   public Car(string petName, int currSpeed)
 7   {
 8       this.petName = petName;
 9       this.currSpeed = currSpeed;
10   }      
11 }        

一旦定义了自定义构造函数,默认构造函数就被自动从类中移除了,这时的new Car();将会引起编译器错误: “Car”不包含采用“0”个参数的构造函数

如果我们希望使用默认构造函数和自定义构造函数来创建类的实例的话,就必须也提供显式的默认构造函数才可以。

 

在C#中有一个this关键字(上面的代码已经用到了),这个关键字用在构造函数上可以实现一种叫构造函数链的用法。当我们为类定义了多个构造函数时,这个模式就会很有用。我们来看代码:

 1 class Car
 2 {
 3     public string petName;
 4     public int currSpeed;
 5 
 6     public Car()
 7     {
 8         this.petName = "myCar";
 9     }
10     public Car(int currSpeed)
11     {
12         if (currSpeed > 100) currSpeed = 100;
13         this.currSpeed = currSpeed;
14     }
15     public Car(string petName, int currSpeed)
16     {
17         this.petName = petName;
18 
19         if (currSpeed > 100) currSpeed = 100;
20         this.currSpeed = currSpeed;
21     }
22 }

上面的代码中存在验证逻辑的代码冗余,这时使用串联法来重新定义,让那个接收参数最多的构造函数来充当主构造函数,在这个构造函数中实现必要的逻辑验证,其余的构造函数使用this关键字把传入的参数转发给主构造函数,并提供所有必要的其他参数就可以了,我们改进一下上面的代码:

 1     class Car
 2     {
 3         public string petName;
 4         public int currSpeed;
 5 
 6         public Car()
 7         {
 8             this.petName = "myCar";
 9         }
10         public Car(int currSpeed) : this("", currSpeed) { }
11         public Car(string petName, int currSpeed)
12         {
13             this.petName = petName;
14 
15             if (currSpeed > 100) currSpeed = 100;
16             this.currSpeed = currSpeed;
17         }
18     }

使用这个技术可以帮助我们简化编程任务,真正的工作将由那个主构造函数来完成,其他构造函数只是将“皮球”踢给了这个主构造函数。那么我们来看以下他的调用顺序是怎样的, 我们使用只有一个参数的构造函数来创建类的实例:如下

 1     class Car
 2     {
 3         public string petName;
 4         public int currSpeed;
 5 
 6         public Car()
 7         {
 8             this.petName = "myCar";
 9         }
10         public Car(int currSpeed) : this("", currSpeed) { Console.WriteLine("只有一个参数的构造函数。"); }
11         public Car(string petName, int currSpeed)
12         {
13             Console.WriteLine("有两个参数的构造函数。");
14             this.petName = petName;
15 
16             if (currSpeed > 100) currSpeed = 100;
17             this.currSpeed = currSpeed;
18         }
19     }
1 static void Main(string[] args)
2 {
3     Car car = new Car(90);
4 
5     Console.ReadLine();
6 }

这时输出的结果如下:

有两个参数的构造函数。
只有一个参数的构造函数。

结果很明显,我们在给构造函数传入一个参数时,编译器调用只有一个参数的构造函数,这时这个构造函数又将参数发送给了主构造函数,最终是由主构造函数完成实例化(其实可理解为是一个参数的构造函数又调用了主构造函数),主构造函数完成后返回到最初调用的构造函数里,并执行剩下的代码。

 

C#还支持静态构造函数,静态构造函数适用于初始化在编译时未知的静态数据的值。下面是关于静态构造函数的几点说明:

  • 一个类只能有一个静态构造函数,也就是说静态构造函数不能被重载;
  • 静态构造函数不允许有访问修饰符,并且不接受任何参数;
  • 不管创建多少个类的实例,静态构造函数只执行一次(在创建类实例或首次访问静态成员之前,静态构造函数会被调用);
  • 静态构造函数的执行先于任何实例级别的构造函数。

如果一个类的构造函数的访问修饰符被定义为private,则这个类将不能被用来实例化对象。

posted @ 2015-07-26 16:47  MrX1892  阅读(529)  评论(0编辑  收藏  举报