构造函数的运用,体现类的自我维护

本文探讨了构造函数在类设计中的重要性,通过多个示例展示了如何利用构造函数提高代码的安全性和简洁性,包括初始化只读成员变量及提供不同级别的对象创建方式。
构造函数有很多用处,巧妙地运用构造函数能提高类的设计安全、合理和封装。

下面的类设计的不合理,要求用户在调用18行Pring方法前,先为17行赋值。
1None.gifpublicclassSpace
2ExpandedBlockStart.gifContractedBlock.gifdot.gif{
3InBlock.gif
4InBlock.gifpublicstaticvoidMain(string[]args)
5ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{
6InBlock.gif
7InBlock.gifFilePrintpring=newFilePrint();
8InBlock.gif//如果用户忘记调用FileName,系统将不可靠
9InBlock.gif//pring.FileName=@"c:/text.txt";
10InBlock.gifpring.Print();
11ExpandedSubBlockEnd.gif}

12ExpandedBlockEnd.gif}

13None.gif
14None.gifpublicclassFilePrint
15ExpandedBlockStart.gifContractedBlock.gifdot.gif{
16InBlock.gif
17InBlock.gifpublicstringFileName=null;
18InBlock.gifpublicvoidPrint()
19ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{
20InBlock.gifSystem.Console.WriteLine("Doprining{0}",FileName);
21ExpandedSubBlockEnd.gif}

22ExpandedBlockEnd.gif}
把代码改为下面就合理的多
1None.gifpublicclassSpace
2ExpandedBlockStart.gifContractedBlock.gifdot.gif{
3InBlock.gif
4InBlock.gifpublicstaticvoidMain(string[]args)
5ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{
6InBlock.gif
7InBlock.gifFilePrintpring=newFilePrint(@"c:/text.txt");
8InBlock.gifpring.Print();
9InBlock.gif
10InBlock.gif//代码可以更简约
11InBlock.gifnewFilePrint(@"c:/text.txt").Print();
12ExpandedSubBlockEnd.gif}

13ExpandedBlockEnd.gif}

14None.gif
15None.gifpublicclassFilePrint
16ExpandedBlockStart.gifContractedBlock.gifdot.gif{
17InBlock.gif
18InBlock.gifpublicFilePrint(stringpath)
19ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{
20InBlock.gifFileName=path;
21ExpandedSubBlockEnd.gif}

22InBlock.gif
23InBlock.gifpublicreadonlystringFileName=null;
24InBlock.gifpublicvoidPrint()
25ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{
26InBlock.gifSystem.Console.WriteLine("Doprining{0}",FileName);
27ExpandedSubBlockEnd.gif}

28ExpandedBlockEnd.gif}

通过构造函数,强制用户在实例化的时候给与FileName的值,调用更安全更简约。
第23行对数据成员FileName修饰为readonly表示该数据成员为只读,只读的意思是,该成员只有一次赋值的机会(声明时立即赋值或在构造函数时赋值)。readonly和const的区别是
readonly有两种赋值的机会:声明时立即赋值或在构造函数时赋值
const只有在声明时赋值

另外一个很值得注意的是,const其实就是static数据修饰,不过不能直接用static来修饰。const包括了static的含义,所以const需要通过类来访问。


我们再来看一个构造函数的运用

请仔细考虑一下代码
1None.gifpublicclassSpace
2ExpandedBlockStart.gifContractedBlock.gifdot.gif{
3InBlock.gif
4InBlock.gifpublicstaticvoidMain(string[]args)
5ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{
6InBlock.gif
7InBlock.gifSystem.Console.WriteLine(newSalesContract(100).SalePrice);
8InBlock.gifSystem.Console.WriteLine(newSalesContract(100,120).SalePrice);
9InBlock.gifSystem.Console.WriteLine(newSalesContract(100,120,180).SalePrice);
10InBlock.gif
11InBlock.gif
12ExpandedSubBlockEnd.gif}

13ExpandedBlockEnd.gif}

14None.gif
15None.gifpublicclassSalesContract:Contract//销售合同
16ExpandedBlockStart.gifContractedBlock.gifdot.gif{
17InBlock.gifpublicSalesContract(doublecostPrice)
18InBlock.gif:this(costPrice,costPrice)
19ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{}
20InBlock.gif
21InBlock.gifpublicSalesContract(doublecostPrice,doubleminimumPrice)
22InBlock.gif:this(costPrice,minimumPrice,minimumPrice)
23ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{}
24InBlock.gif
25InBlock.gifpublicSalesContract(doublecostPrice,doubleminimumPrice,doublesalePrice)
26ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{
27InBlock.gifCostPrice=costPrice;
28InBlock.gifMinimumPrice=minimumPrice;
29InBlock.gifSalePrice=salePrice;
30ExpandedSubBlockEnd.gif}

31InBlock.gif
32InBlock.gifprivatedoubleMinimumPrice;//最低价
33InBlock.gifpublicdoubleSalePrice;//销售价格
34InBlock.gif
35InBlock.gifpublicboolCheckPrice()//价格检查
36ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{
37InBlock.gifreturnSalePrice<Math.Min(MinimumPrice,CostPrice);
38ExpandedSubBlockEnd.gif}

39InBlock.gifinternaldoublePreferentialPrice;//优惠价
40ExpandedBlockEnd.gif}

41None.gif
42None.gifpublicclassContract//合同
43ExpandedBlockStart.gifContractedBlock.gifdot.gif{
44InBlock.gif
45InBlock.gifpublicstringBuyer;//买方
46InBlock.gifpublicstringSeller;//卖方
47InBlock.gifprotecteddoubleCostPrice;//成本价
48ExpandedBlockEnd.gif}


通过3个构造函数,用户可以方便的对ConstPrice、SalePrice、MinimunPrice进行赋值。

我们再来看一个关于构造函数的用例。

1None.gifpublicclassSpace
2ExpandedBlockStart.gifContractedBlock.gifdot.gif{
3InBlock.gif
4InBlock.gifpublicstaticvoidMain(string[]args)
5ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{
6InBlock.gifSystem.Console.WriteLine(newOrder("123-12").OrderNumber);
7InBlock.gifSystem.Console.WriteLine(newOrder(Order.CreateOrderNumber()).OrderNumber);
8InBlock.gifSystem.Console.WriteLine(newOrder(Order.CreateOrderNumber()).OrderNumber);
9ExpandedSubBlockEnd.gif}

10ExpandedBlockEnd.gif}

11None.gif
12None.gifpublicclassOrder
13ExpandedBlockStart.gifContractedBlock.gifdot.gif{
14InBlock.gif
15InBlock.gifpublicOrder(stringorderNumber)
16ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{
17InBlock.gifthis.OrderNumber=orderNumber;
18ExpandedSubBlockEnd.gif}

19InBlock.gif
20InBlock.gifprivatestaticintCount;
21InBlock.gif
22InBlock.gifpublicreadonlystringOrderNumber;
23InBlock.gif
24InBlock.gifpublicstaticstringCreateOrderNumber()
25ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{
26InBlock.gifSystem.DateTimed=System.DateTime.Now;
27InBlock.gifreturnSystem.DateTime.Now.ToString("yMd-")+(++Count).ToString();
28ExpandedSubBlockEnd.gif}

29InBlock.gif
30ExpandedBlockEnd.gif}

上面的代码看似很合理,用户可以自己定义OrderNumber也可以通过CreateOrderNumber方法,Order在构造时总是可以得到Number。

但这样的设计,暴露了对CreateOrderNumber的调用。

我们看看经过修改后的设计

1None.gifpublicclassOrder
2ExpandedBlockStart.gifContractedBlock.gifdot.gif{
3InBlock.gif
4InBlock.gifpublicOrder(stringorderNumber)
5ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{
6InBlock.gifthis.OrderNumber=orderNumber;
7ExpandedSubBlockEnd.gif}

8InBlock.gif
9InBlock.gifpublicOrder():this(CreateOrderNumber())
10ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{
11InBlock.gif
12ExpandedSubBlockEnd.gif}

13InBlock.gif
14InBlock.gifprivatestaticintCount;
15InBlock.gif
16InBlock.gifpublicreadonlystringOrderNumber;
17InBlock.gif
18InBlock.gifprivatestaticstringCreateOrderNumber()
19ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{
20InBlock.gifSystem.DateTimed=System.DateTime.Now;
21InBlock.gifreturnSystem.DateTime.Now.ToString("yMd-")+(++Count).ToString();
22ExpandedSubBlockEnd.gif}

23InBlock.gif
24ExpandedBlockEnd.gif}

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

1None.gifpublicclassSpace
2ExpandedBlockStart.gifContractedBlock.gifdot.gif{
3InBlock.gif
4InBlock.gifpublicstaticvoidMain(string[]args)
5ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{
6InBlock.gifSystem.Console.WriteLine(newOrder("123-12").OrderNumber);
7InBlock.gifSystem.Console.WriteLine(newOrder().OrderNumber);
8InBlock.gifSystem.Console.WriteLine(newOrder().OrderNumber);
9ExpandedSubBlockEnd.gif}

10ExpandedBlockEnd.gif}

看到了吗?在这个代码中,如果用户给与了Number则使用用户给与的值,否则,Order能自动给与值。向用户封装了CreateOrderNumber的存在。这就是类设计的一个很重要的原则:自我维护。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值