构造函数有很多用处,巧妙地运用构造函数能提高类的设计安全、合理和封装。
下面的类设计的不合理,要求用户在调用18行Pring方法前,先为17行赋值。
通过构造函数,强制用户在实例化的时候给与FileName的值,调用更安全更简约。
第23行对数据成员FileName修饰为readonly表示该数据成员为只读,只读的意思是,该成员只有一次赋值的机会(声明时立即赋值或在构造函数时赋值)。readonly和const的区别是
readonly有两种赋值的机会:声明时立即赋值或在构造函数时赋值
const只有在声明时赋值
另外一个很值得注意的是,const其实就是static数据修饰,不过不能直接用static来修饰。const包括了static的含义,所以const需要通过类来访问。
我们再来看一个构造函数的运用
请仔细考虑一下代码
下面的类设计的不合理,要求用户在调用18行Pring方法前,先为17行赋值。
1
publicclassSpace
2

{
3
4
publicstaticvoidMain(string[]args)
5

{
6
7
FilePrintpring=newFilePrint();
8
//如果用户忘记调用FileName,系统将不可靠
9
//pring.FileName=@"c:/text.txt";
10
pring.Print();
11
}
12
}
13
14
publicclassFilePrint
15

{
16
17
publicstringFileName=null;
18
publicvoidPrint()
19

{
20
System.Console.WriteLine("Doprining{0}",FileName);
21
}
22
}
把代码改为下面就合理的多
publicclassSpace2


{3

4
publicstaticvoidMain(string[]args)5


{6

7
FilePrintpring=newFilePrint();8
//如果用户忘记调用FileName,系统将不可靠9
//pring.FileName=@"c:/text.txt";10
pring.Print();11
}12
}13

14
publicclassFilePrint15


{16

17
publicstringFileName=null;18
publicvoidPrint()19


{20
System.Console.WriteLine("Doprining{0}",FileName);21
}22
}
1
publicclassSpace
2

{
3
4
publicstaticvoidMain(string[]args)
5

{
6
7
FilePrintpring=newFilePrint(@"c:/text.txt");
8
pring.Print();
9
10
//代码可以更简约
11
newFilePrint(@"c:/text.txt").Print();
12
}
13
}
14
15
publicclassFilePrint
16

{
17
18
publicFilePrint(stringpath)
19

{
20
FileName=path;
21
}
22
23
publicreadonlystringFileName=null;
24
publicvoidPrint()
25

{
26
System.Console.WriteLine("Doprining{0}",FileName);
27
}
28
}
publicclassSpace2


{3

4
publicstaticvoidMain(string[]args)5


{6

7
FilePrintpring=newFilePrint(@"c:/text.txt");8
pring.Print();9

10
//代码可以更简约11
newFilePrint(@"c:/text.txt").Print();12
}13
}14

15
publicclassFilePrint16


{17

18
publicFilePrint(stringpath)19


{20
FileName=path;21
}22

23
publicreadonlystringFileName=null;24
publicvoidPrint()25


{26
System.Console.WriteLine("Doprining{0}",FileName);27
}28
}
通过构造函数,强制用户在实例化的时候给与FileName的值,调用更安全更简约。
第23行对数据成员FileName修饰为readonly表示该数据成员为只读,只读的意思是,该成员只有一次赋值的机会(声明时立即赋值或在构造函数时赋值)。readonly和const的区别是
readonly有两种赋值的机会:声明时立即赋值或在构造函数时赋值
const只有在声明时赋值
另外一个很值得注意的是,const其实就是static数据修饰,不过不能直接用static来修饰。const包括了static的含义,所以const需要通过类来访问。
我们再来看一个构造函数的运用
请仔细考虑一下代码
1
publicclassSpace
2

{
3
4
publicstaticvoidMain(string[]args)
5

{
6
7
System.Console.WriteLine(newSalesContract(100).SalePrice);
8
System.Console.WriteLine(newSalesContract(100,120).SalePrice);
9
System.Console.WriteLine(newSalesContract(100,120,180).SalePrice);
10
11
12
}
13
}
14
15
publicclassSalesContract:Contract//销售合同
16

{
17
publicSalesContract(doublecostPrice)
18
:this(costPrice,costPrice)
19

{}
20
21
publicSalesContract(doublecostPrice,doubleminimumPrice)
22
:this(costPrice,minimumPrice,minimumPrice)
23

{}
24
25
publicSalesContract(doublecostPrice,doubleminimumPrice,doublesalePrice)
26

{
27
CostPrice=costPrice;
28
MinimumPrice=minimumPrice;
29
SalePrice=salePrice;
30
}
31
32
privatedoubleMinimumPrice;//最低价
33
publicdoubleSalePrice;//销售价格
34
35
publicboolCheckPrice()//价格检查
36

{
37
returnSalePrice<Math.Min(MinimumPrice,CostPrice);
38
}
39
internaldoublePreferentialPrice;//优惠价
40
}
41
42
publicclassContract//合同
43

{
44
45
publicstringBuyer;//买方
46
publicstringSeller;//卖方
47
protecteddoubleCostPrice;//成本价
48
}
publicclassSpace2


{3

4
publicstaticvoidMain(string[]args)5


{6

7
System.Console.WriteLine(newSalesContract(100).SalePrice);8
System.Console.WriteLine(newSalesContract(100,120).SalePrice);9
System.Console.WriteLine(newSalesContract(100,120,180).SalePrice);10

11

12
}13
}14

15
publicclassSalesContract:Contract//销售合同16


{17
publicSalesContract(doublecostPrice)18
:this(costPrice,costPrice)19


{}20

21
publicSalesContract(doublecostPrice,doubleminimumPrice)22
:this(costPrice,minimumPrice,minimumPrice)23


{}24

25
publicSalesContract(doublecostPrice,doubleminimumPrice,doublesalePrice)26


{27
CostPrice=costPrice;28
MinimumPrice=minimumPrice;29
SalePrice=salePrice;30
}31

32
privatedoubleMinimumPrice;//最低价33
publicdoubleSalePrice;//销售价格34

35
publicboolCheckPrice()//价格检查36


{37
returnSalePrice<Math.Min(MinimumPrice,CostPrice);38
}39
internaldoublePreferentialPrice;//优惠价40
}41

42
publicclassContract//合同43


{44

45
publicstringBuyer;//买方46
publicstringSeller;//卖方47
protecteddoubleCostPrice;//成本价48
}
通过3个构造函数,用户可以方便的对ConstPrice、SalePrice、MinimunPrice进行赋值。
我们再来看一个关于构造函数的用例。
1
publicclassSpace
2

{
3
4
publicstaticvoidMain(string[]args)
5

{
6
System.Console.WriteLine(newOrder("123-12").OrderNumber);
7
System.Console.WriteLine(newOrder(Order.CreateOrderNumber()).OrderNumber);
8
System.Console.WriteLine(newOrder(Order.CreateOrderNumber()).OrderNumber);
9
}
10
}
11
12
publicclassOrder
13

{
14
15
publicOrder(stringorderNumber)
16

{
17
this.OrderNumber=orderNumber;
18
}
19
20
privatestaticintCount;
21
22
publicreadonlystringOrderNumber;
23
24
publicstaticstringCreateOrderNumber()
25

{
26
System.DateTimed=System.DateTime.Now;
27
returnSystem.DateTime.Now.ToString("yMd-")+(++Count).ToString();
28
}
29
30
}
publicclassSpace2


{3

4
publicstaticvoidMain(string[]args)5


{6
System.Console.WriteLine(newOrder("123-12").OrderNumber);7
System.Console.WriteLine(newOrder(Order.CreateOrderNumber()).OrderNumber);8
System.Console.WriteLine(newOrder(Order.CreateOrderNumber()).OrderNumber);9
}10
}11

12
publicclassOrder13


{14

15
publicOrder(stringorderNumber)16


{17
this.OrderNumber=orderNumber;18
}19

20
privatestaticintCount;21

22
publicreadonlystringOrderNumber;23

24
publicstaticstringCreateOrderNumber()25


{26
System.DateTimed=System.DateTime.Now;27
returnSystem.DateTime.Now.ToString("yMd-")+(++Count).ToString();28
}29

30
}
上面的代码看似很合理,用户可以自己定义OrderNumber也可以通过CreateOrderNumber方法,Order在构造时总是可以得到Number。
但这样的设计,暴露了对CreateOrderNumber的调用。
我们看看经过修改后的设计
1
publicclassOrder
2

{
3
4
publicOrder(stringorderNumber)
5

{
6
this.OrderNumber=orderNumber;
7
}
8
9
publicOrder():this(CreateOrderNumber())
10

{
11
12
}
13
14
privatestaticintCount;
15
16
publicreadonlystringOrderNumber;
17
18
privatestaticstringCreateOrderNumber()
19

{
20
System.DateTimed=System.DateTime.Now;
21
returnSystem.DateTime.Now.ToString("yMd-")+(++Count).ToString();
22
}
23
24
}
publicclassOrder2


{3

4
publicOrder(stringorderNumber)5


{6
this.OrderNumber=orderNumber;7
}8

9
publicOrder():this(CreateOrderNumber())10


{11

12
}13

14
privatestaticintCount;15

16
publicreadonlystringOrderNumber;17

18
privatestaticstringCreateOrderNumber()19


{20
System.DateTimed=System.DateTime.Now;21
returnSystem.DateTime.Now.ToString("yMd-")+(++Count).ToString();22
}23

24
}
我们添加了一个默认的构造函数Order()在第9行,又把18行的CreateOrderNumber改为private,那么这会有什么效果呢?
1
publicclassSpace
2

{
3
4
publicstaticvoidMain(string[]args)
5

{
6
System.Console.WriteLine(newOrder("123-12").OrderNumber);
7
System.Console.WriteLine(newOrder().OrderNumber);
8
System.Console.WriteLine(newOrder().OrderNumber);
9
}
10
}
publicclassSpace2


{3

4
publicstaticvoidMain(string[]args)5


{6
System.Console.WriteLine(newOrder("123-12").OrderNumber);7
System.Console.WriteLine(newOrder().OrderNumber);8
System.Console.WriteLine(newOrder().OrderNumber);9
}10
}
看到了吗?在这个代码中,如果用户给与了Number则使用用户给与的值,否则,Order能自动给与值。向用户封装了CreateOrderNumber的存在。这就是类设计的一个很重要的原则:自我维护。
本文探讨了构造函数在类设计中的重要性,通过多个示例展示了如何利用构造函数提高代码的安全性和简洁性,包括初始化只读成员变量及提供不同级别的对象创建方式。
1380

被折叠的 条评论
为什么被折叠?



