在我最初學習面向對象的時候,對封裝性的好處並沒有什么深入的理解,只是覺得外界看不見了而已。直到最近我學習C#事件對委托的封裝,加上看了一些網上的資料,才加深了對封裝的體會。
根據我現在的理解,封裝有如下好處:
1)對象封裝后,外面只能查看或是賦值,卻不能使用它
具體怎么使用只能由類內部自己決定,這樣避免了在主程序中使用它的行為。因為若在主程序中使用它,有可能會錯失一些該對象本該在類中處理的行為。
public delegate double PriceHandler(); public class PriceManager { public PriceHandler GetPriceHandler; //委托處理,當價格高於100元按8.8折計算,其他按原價計算 public double GetPrice() { if (GetPriceHandler.GetInvocationList().Count() > 0) { if (GetPriceHandler() > 100) return GetPriceHandler()*0.88; else return GetPriceHandler(); } return -1; } } class Program { static void Main(string[] args) { PriceManager priceManager = new PriceManager(); priceManager.GetPriceHandler = new PriceHandler(ComputerPrice);
//調用priceManager的GetPrice方法獲取價格 Console.WriteLine(string.Format("GetPrice\n Computer's price is {0}!", priceManager.GetPrice()));
//由於委托GetPriceHandler未封裝,主程序就可以只用使用它,導致它沒有經過GetPrice方法的判斷,導致價格沒打8折而直接返回原值 Console.WriteLine(string.Format("Invoke\n Computer's price is {0}!", priceManager.GetPriceHandler.Invoke())); Console.ReadKey(); } //計算機價格為8800元 public static double ComputerPrice() { return 8800.0; } }
很顯然如果GetPriceHandler 設置為 public ,外界可以直接調用 GetPriceHandler.Invoke 獲取運行結果而移除了 GetPrice 方法的處理,導致電腦價格沒有打折。
2)封裝對象后,類的實現修改后,只用修改類而無需修改客戶端代碼
假設類A中定義了一個未封裝的int age類型字段,那么客戶端給age賦值時為A.age = 5。如果需求更改,A中變為string age字段,那么所有客戶端中給age賦值的代碼都要變為A.age = "5"。這樣當客戶端大量使用時,這樣的工作是很大的。
但如果A中的age字段被封裝了,那客戶端仍可向往常一樣當做整形賦值,只需要把傳進來的值轉換為string類型即可。
3)封裝對象后,能實現更好的對象控制
這其實與第二點類似,因為封裝就相當於一個客戶端和類端的中間者。
對於客戶端來說,對象封裝后,我永遠就只能以一種形式查看對象、給對象賦值,且無法使用該對象。
對於類端來說,對象封裝后,當客戶端賦值時,我從封裝這個中間者拿到值,之后怎么處理就看我自己了,比如客戶端賦值為int,而我想要string,那只需做一個強制轉換即可。