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

构造函数有很多用处,巧妙地运用构造函数能提高类的设计安全、合理和封装。

下面的类设计的不合理,要求用户在调用18行Pring方法前,先为17行赋值。
 1    public class Space
 2    {
 3
 4        public static void Main(string[] args)
 5        {
 6
 7            FilePrint pring = new FilePrint();
 8            //如果用户忘记调用FileName,系统将不可靠
 9            //pring.FileName = @"c:\text.txt";
10            pring.Print();
11        }

12    }

13
14    public class FilePrint
15    {
16
17        public string FileName = null;
18        public void Print()
19        {
20            System.Console.WriteLine("Do prining {0}", FileName);
21        }

22    }
把代码改为下面就合理的多
 1    public class Space
 2    {
 3
 4        public static void Main(string[] args)
 5        {
 6
 7            FilePrint pring = new FilePrint(@"c:\text.txt");
 8            pring.Print();
 9
10            //代码可以更简约
11            new FilePrint(@"c:\text.txt").Print();
12        }

13    }

14
15    public class FilePrint
16    {
17
18        public FilePrint(string path)
19        {
20            FileName = path;
21        }

22
23        public readonly string FileName = null;
24        public void Print()
25        {
26            System.Console.WriteLine("Do prining {0}", FileName);
27        }

28    }

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

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


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

请仔细考虑一下代码
 1    public class Space
 2    {
 3
 4        public static void Main(string[] args)
 5        {
 6
 7            System.Console.WriteLine(new SalesContract(100).SalePrice);
 8            System.Console.WriteLine(new SalesContract(100,120).SalePrice);
 9            System.Console.WriteLine(new SalesContract(100,120,180).SalePrice);
10
11
12        }

13    }

14
15    public class SalesContract : Contract//销售合同 
16    {
17        public SalesContract(double costPrice)
18            : this(costPrice, costPrice)
19        { }
20
21        public SalesContract(double costPrice, double minimumPrice)
22            : this(costPrice, minimumPrice, minimumPrice)
23        { }
24
25        public SalesContract(double costPrice, double minimumPrice, double salePrice)
26        {
27            CostPrice = costPrice;
28            MinimumPrice = minimumPrice;
29            SalePrice = salePrice;
30        }

31
32        private double MinimumPrice;//最低价
33        public double SalePrice;//销售价格  
34
35        public bool CheckPrice()//价格检查
36        {
37            return SalePrice < Math.Min(MinimumPrice, CostPrice);
38        }

39        internal double PreferentialPrice;//优惠价
40    }

41
42    public class Contract//合同
43    {
44
45        public string Buyer;//买方
46        public string Seller;//卖方
47        protected double CostPrice;//成本价
48    }


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

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

 1    public class Space
 2    {
 3
 4        public static void Main(string[] args)
 5        {
 6            System.Console.WriteLine(new Order("123-12").OrderNumber);
 7            System.Console.WriteLine(new Order(Order.CreateOrderNumber()).OrderNumber);
 8            System.Console.WriteLine(new Order(Order.CreateOrderNumber()).OrderNumber);
 9        }

10    }

11
12    public class Order
13    {
14
15        public Order(string orderNumber)
16        {
17            this.OrderNumber = orderNumber;
18        }

19
20        private static int Count;
21
22        public readonly string OrderNumber;
23
24        public static string CreateOrderNumber()
25        {
26            System.DateTime d = System.DateTime.Now;
27            return System.DateTime.Now.ToString("yMd-"+ (++Count).ToString();
28        }

29
30    }

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

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

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

 1    public class Order
 2    {
 3
 4        public Order(string orderNumber)
 5        {
 6            this.OrderNumber = orderNumber;
 7        }

 8
 9        public Order():this(CreateOrderNumber())
10        
11        
12        }

13
14        private static int Count;
15
16        public readonly string OrderNumber;
17
18        private static string CreateOrderNumber()
19        {
20            System.DateTime d = System.DateTime.Now;
21            return System.DateTime.Now.ToString("yMd-"+ (++Count).ToString();
22        }

23
24    }

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

 1    public class Space
 2    {
 3
 4        public static void Main(string[] args)
 5        {
 6            System.Console.WriteLine(new Order("123-12").OrderNumber);
 7            System.Console.WriteLine(new Order().OrderNumber);
 8            System.Console.WriteLine(new Order().OrderNumber);
 9        }

10    }

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

原文地址:https://www.cnblogs.com/shyleoking/p/644049.html