C#基础拾遗——构造函数
近来想了解下C#4.0的新特性,毕竟平时做项目用的都还是2.0的语法 - -。
拿了本高级教程第七版的,新书有爱啊,老习惯将目录和引文遛一边先。想着还是都翻把,权当复习和学习。
看到构造函数的时候,虽然之前也是理解过的,但看了后感觉还是有必要笔记下这个过程,当是加深记忆和备忘。
这个知识点重要的就是理解构造函数的创建过程。
看例子:
1 class people
2 {
3 protected string name;
4
5 }
6
7 class mm : people
8 {
9 private int _age;
10
11 public void say()
12 {
13 Console.Write(this._age + "," + base.name);
14 }
15
16 }
17
18 class Program
19 {
20 static void Main(string[] args)
21 {
22 mm mmm = new mm();
23 mmm.say(); //结果是:0, ;
24 Console.ReadLine();
25 }
26 }
例子很简单,结果也很容易猜到。再改下这个列子:
1 class people
2 {
3 protected string _name;
4
5 private people()
6 {
7
8 }
9 }
10
11 class mm : people
12 {
13 private int _age;
14
15 public void say()
16 {
17 Console.Write(this._age + "," + base._name);
18 }
19
20 }
这样的话,编译就出错了说是:“ConstructorTest.people.people()”不可访问,因为它受保护级别限制。
原因是第5行我将构造函数私有了。
了解类的初始化过程的就很清楚我为什么要弄这两个列子,其实重错误信息也可以看出端倪。
我主要就是想说清楚继承下的多层次结构中对象的初始化过程。
不清楚的看下图就什么都清楚了:
当我们执行
1 mm mmm = new mm();
我们知道,构造函数的作用就是在创建实例化对象时初始化自身的数据变量。而上面的例子中,MM在初始化自己的时候会去调他的父类People的构造方法去初始化People,而People要自己又得去调他自身父类的构造函数,这样一直向上找直到“万物之源”Object。其实这个也挺好理解的,这就是个阶级社会,小弟门弄到吃的先给自己的老二,老二自己不敢吃要先给老大,Obejct就是老大,他先自己吃饱了(自己初始化了),然后在把剩下的给老二(初始化),老二吃剩的给小弟(初始化)。
这个过程是比较好理解的,但是在这个过程中有几点是需要注意的。
1.若在调用父类的构造函数的时候,父类没有显式的构造函数可调的时候,编译器会为其创建默认构造函数(无参空操作),他的作用是将变量赋空值,就像第一个例子那样,int类型赋的是0,string的是null。
2.在调用的时候,父类若显式的写了构造函数,那么构造函数的访问级别必须是子类可以访问到的(即不能为private)。就像第二个例子,去初始MM的时候,由于MM没有显式的构造函数,那么编译器就会为其创建一个默认的构造函数,然后他试图去调用父类的无参构造函数,而这时候由于父类已经有了显式构造函数所以他不会去创建,但这个构造函数却是private的,子类无法调用到,所以在这里创建过程就失败了,即出错了。
3.默认下下列的写法是等价的,但是对于理解的作用是比较有用的。
1 class people
2 {
3 protected string _name;
4 //用base()说明去调他父类构造函数
5 //空构造函数写不写:base()是一样的
6 //但要初始父类中的一些变量,就通过:base(xxx)传参给父类
7 public people()
8 : base()
9 {
10
11 }
12
13 }
14
15 class mm : people
16 {
17 private int _age;
18
19 public mm()
20 : base()
21 {
22 }
23
24 public void say()
25 {
26 Console.Write(this._age + "," + base._name);
27 }
28
29 }
创建过程就是这样子,明白了后就可以自己控制继承下多层结构的初始化过程了。