在我最初学习面向对象的时候,对封装性的好处并没有什么深入的理解,只是觉得外界看不见了而已。直到最近我学习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 Computer's price is {0}!", priceManager.GetPrice()));
//由于委托GetPriceHandler未封装,主程序就可以只用使用它,导致它没有经过GetPrice方法的判断,导致价格没打8折而直接返回原值 Console.WriteLine(string.Format("Invoke 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,那只需做一个强制转换即可。