一、封裝 下麵我設計了一個空調類,對於要使用這個空調類的其他類我可以稱它們為用戶。用戶需要瞭解空調類的使用方法,才能更好的使用空調。空調類如下: 用戶使用我設計的空調類,如果他對使用方法不太熟,它可能給空調上下方向設置成5或者其它數字;或者今天天氣特別熱,它把空調溫度設置成0度甚至更低,或者失誤設置 ...
一、封裝
下麵我設計了一個空調類,對於要使用這個空調類的其他類我可以稱它們為用戶。用戶需要瞭解空調類的使用方法,才能更好的使用空調。空調類如下:
1 public class Air 2 { 3 /// <summary> 4 /// 空調溫度 5 /// </summary> 6 public int temperature; 7 8 /// <summary> 9 /// 空調上下方向(用int量化方向,0代表下,1代表中下,2代表中,3代表中上,4代表上) 10 /// </summary> 11 public int verticalDirection; 12 13 /// <summary> 14 /// 空調開關(false代表關,true代表開) 15 /// </summary> 16 public bool switch_C; 17 18 public Air() 19 { 20 temperature = 28; 21 verticalDirection = 3; 22 switch_C = false; 23 } 24 }
用戶使用我設計的空調類,如果他對使用方法不太熟,它可能給空調上下方向設置成5或者其它數字;或者今天天氣特別熱,它把空調溫度設置成0度甚至更低,或者失誤設置成100度。
1 public class User 2 { 3 public void UseAir() 4 { 5 Air air = new Air(); 6 air.switch_C = true; 7 air.verticalDirection = 5; //空調上下方向沒有5這個設置 8 air.temperature = 0; //空調溫度設置成0度 9 air.temperature = 100; //如果我的空調類什麼溫度都能達到,那可能要用戶老命!!! 10 } 11 }
可以看出我的空調類設計得有問題,我應該限制空調溫度和空調上下方向的設置範圍,那麼首先用戶不能直接設置它們的值,所以我要把空調溫度和空調上下方向定義成私有的,然後設計公共方法來限制它們的設置範圍,同時還要設計公共方法為用戶提供查詢操作。空調開關也可以通過這種方式簡化用戶操作。第二版空調類如下:
1 public class Air 2 { 3 /// <summary> 4 /// 空調溫度 5 /// </summary> 6 private int temperature; 7 8 /// <summary> 9 /// 空調上下方向(用int量化方向,0代表下,1代表中下,2代表中,3代表中上,4代表上) 10 /// </summary> 11 private int verticalDirection; 12 13 /// <summary> 14 /// 空調開關(false代表關,true代表開) 15 /// </summary> 16 private bool switch_C; 17 18 19 /// <summary> 20 /// 獲取空調溫度 21 /// </summary> 22 public int GetTemperature() 23 { 24 return temperature; 25 } 26 27 /// <summary> 28 /// 設置空調溫度 29 /// </summary> 30 /// <param name="degree"></param> 31 public void SetTemperature(int degree) 32 { 33 if (degree > 16 && degree < 30) 34 { 35 temperature = degree; 36 } 37 else 38 { 39 //提示設置錯誤 40 } 41 } 42 43 /// <summary> 44 /// 獲取空調上下方向 45 /// </summary> 46 /// <returns></returns> 47 public int GetVerticalDirection() 48 { 49 return verticalDirection; 50 } 51 52 /// <summary> 53 /// 設置空調上下方向 54 /// </summary> 55 /// <param name="direction"></param> 56 public void SetVerticalDirection(int direction) 57 { 58 if (direction >= 0 && direction < 5) 59 { 60 verticalDirection = direction; 61 } 62 else 63 { 64 //提示設置錯誤 65 } 66 } 67 68 public bool GetSwitch() 69 { 70 return switch_C; 71 } 72 73 public void SetSwitch() 74 { 75 switch_C = switch_C ? false : true; 76 } 77 78 //---設置有參構造函數時,調用相應set方法做對應限制--- 79 public Air(int num, int upOrdown, bool openOrClose) 80 { 81 SetTemperature(num); 82 SetVerticalDirection(upOrdown); 83 switch_C = openOrClose; 84 } 85 }
上面我設計的第二版空調類所做的事就是封裝,通過相應的Get和Set方法對外公開數據的操作,又能做到相應的限制,即保護欄位數據不出現意外的值,又能對外隱藏操作數據方式的細節(無論SetTemperature方法的實現多麼複雜,用戶只需要知道如何使用就行了,好比你使用空調時只需要知道如何使用空調的功能,而不需要知道空調是如何完成這些功能的)。
二、屬性
屬性是對Get方法和Set方法的簡化形式,也是C#提供的強制封裝欄位的方式。除此之外,它的最大優勢是可以像使用欄位一樣使用屬性。只讀屬性和只寫屬性即只有Get方法的屬性和只有Set方法的屬性。屬性版空調類如下:
1 public class Air 2 { 3 private int temperature; 4 private int verticalDirection; 5 private bool switch_C; 6 7 /// <summary> 8 /// 空調溫度的屬性(屬性的返回值類型同對應的欄位類型,屬性的名字一般首字母大寫) 9 /// </summary> 10 public int Temperature 11 { 12 //get作用域等同GetTemperature()方法 13 get { return temperature; } 14 //set作用域等同SetTemperature(int degree)方法,value等於參數degree 15 set 16 { 17 if (value > 16 && value < 30) 18 { 19 temperature = value; 20 } 21 else 22 { 23 //提示設置錯誤 24 } 25 } 26 } 27 28 /// <summary> 29 /// 空調上下方向的屬性 30 /// </summary> 31 public int VerticalDirection 32 { 33 get { return verticalDirection; } 34 set 35 { 36 if (value >= 0 && value < 5) 37 { 38 verticalDirection = value; 39 } 40 else 41 { 42 //提示設置錯誤 43 } 44 } 45 } 46 47 /// <summary> 48 /// 空調開關的屬性 49 /// </summary> 50 public bool Switch_C 51 { 52 //只讀屬性 53 get { return switch_C; } 54 } 55 56 //SetSwitch方法沒有bool參數,不能簡化成屬性,它是一個普通方法 57 public void SetSwitch() 58 { 59 switch_C = switch_C ? false : true; 60 } 61 62 #region 構造函數直接調用屬性,可以做到各司其職,構造函數只做初始化,檢查欄位有效範圍則交給屬性 63 public Air() : this(28, 3, false) { } 64 65 public Air(int num, int upOrdown, bool openOrClose) 66 { 67 Temperature = num; 68 VerticalDirection = upOrdown; 69 //只讀屬性只有Get方法沒有Set方法,所以無法通過構造函數賦值,只能通過為其私有欄位賦值,間接為屬性賦值 70 switch_C = openOrClose; 71 } 72 #endregion 73 } 74 public class User 75 { 76 public void UseAir() 77 { 78 Air air = new Air(); 79 //開啟空調 80 air.Switch_C(); 81 //像欄位一樣使用屬性 82 air.Temperature += 1; 83 air.VerticalDirection = 0; 84 } 85 }
當你獲取屬性的值時執行屬性的get作用域,背後其實調用的是一個無參數且返回值類型同其封裝的欄位類型的方法;當你設置屬性的值時執行屬性的set作用域,背後其實調用的是一個有且僅有一個類型同其封裝的欄位類型的參數且返回值為void的方法。
三、自動屬性
當屬性只對封裝欄位作簡單的包裝時,可以使用自動屬性簡化封裝欄位數據的過程。結構如下:
1 //private int duration; 2 public int Duration 3 { 4 get; //{ return duration; } 5 set; //{ duration = value; } 6 }
自動屬性省略了定義私有欄位和get/set實現邏輯,這些省略的部分會由編譯器在編譯代碼是為其自動生成。
註:自動屬性不應該設計成只讀或只寫自動屬性,因為自動屬性的私有欄位只有在編譯時才生成,寫代碼時沒有私有欄位。代碼如下:
1 public class Air 2 { 3 public int Temperature{ get; } 4 public int VerticalDirection { set; } 5 6 public Air(int num, int upOrdown) 7 { 8 //只讀自動屬性無法賦值,所以永遠不會有值。 9 //Temperature = num; 10 //只寫自動屬性可以賦值,但永遠無法被使用。 11 VerticalDirection = upOrdown; 12 } 13 }