封裝(Encapsulation)是指類別可以控制其成員被其他類別存取的範圍,為物件導向程式的三大特性(封裝,繼承,多型)之一。
物件導向程式(Object-oriented Programming)是透過各種類別(Classes)的實作(Implementations) - 也就是物件(Objects),彼此互相依賴及交互作用來完成程式的功能。
而類別是用來匯集相關資料及行為的一個容器,
例如使用者類別User
可能匯集了姓名,信箱,密碼,電話等資訊;
使用者 User
public class User {
private String name; // 姓名
private String email; // 信箱
private String password; // 密碼
private String phoneNumber; // 電話
}
訂單類別Order
可能匯集了訂單編號,訂單日期,訂購人,收貨人,送貨地址等資訊 ;
訂單 Order
public class Order {
private String orderNo; // 訂單編號
private Date orderDate; // 訂單日期
private User buyer; // 訂購人
private String receiverName; // 收貨人
private String shippingAddress; // 送貨地址等資訊
}
出貨服務類別ShippingService
可能凝聚了出貨相關的行為如出貨,發送出貨通知,扣除存貨數量等。
出貨服務 ShippingService
public class ShippingService {
/** 訂單出貨 */
public void ship() { ... }
/** 出貨通知 */
private void notify() { ... }
/** 扣除存貨數量 */
private void deductStockItemQty() { ... };
}
這些集中在類別的資訊稱為類別的成員變數(member variable),行為則稱為方法(method)。
一個類別是否能引用(reference)/調用(invoke)/呼叫(call)另外一個類別的成員決定於被引用類別中的成員有什麼樣的存取修飾子(Access Modifiers)。
Java的存取修飾子存取範圍由高至低分別為public
,protected
,default
,private
。
下表為存取修飾子的可存取範圍對照表。
public | protected | default | private | |
---|---|---|---|---|
同類別中可存取 | 〇 | 〇 | 〇 | 〇 |
同package的子類別可存取 | 〇 | 〇 | 〇 | X |
同package的非子類別可存取 | 〇 | 〇 | 〇 | X |
不同package的子類別可存取 | 〇 | 〇 | X | X |
不同package的非子類別可存取 | 〇 | X | X | X |
public
成員可被各種類別存取;
protected
成員不能被不同package的非子類別存取;
default
成員無法被不同package的類別或子類別存取;
private
成員只能在同個類別中存取。
例如出貨服務類別ShippingService
出貨ship()
時,可能需要取得使用者User
的信箱email
才能寄送出貨通知;需要訂單Order
的送貨地址shippingAddress
才能確實地將貨品發送到指定的地點。
因此在設計類別時,就必須考慮到類別成員該使用哪種存取修飾子。
例如經常需要被其他類別引用的成員使用public
修飾;
有些成員可能僅在類別中使用,則使用private
修飾;
有些成員可能希望能被繼承的子類別使用,則使用protected
修飾。
以上即為封裝的特性,即類別可控制成員的存取範圍。
那為什麼物件導向要提供封裝的特性呢?封裝有什麼好處?
封裝帶來的好處是,類別能控制其成員能被外部類別看到及使用的範圍,客戶端在使用時無須知道被引用類別的內部實作,客戶端只要知道公開成員被引用時的輸入和輸出是什麼,不用知道類別中未公開成員的細結,如此便可降低開發人員被過多的細節干擾,提高開發效率。此外類別成員及方法被修改時只要對外規格不變(名稱及引數型態不變),就不會影響到客戶端的使用,達到程式間隔離的效果,提高程式的健壯性(robustness)。而類別成員在存取時可在內部進行檢查,篩選,過濾等,增加了資料安全。
所以物件導向的封裝提供了以下好處:
- 隱藏細節,降低複雜度
- 界面隔離,提高健壯性
- 內部檢查,增加安全性
參考:
沒有留言:
張貼留言