設計良好的模組會將 API 及實作清楚的隔離,模組之間用 API 來溝通,一個模組不需要知道其它模組的實作細節,概念稱為訊息隱藏 (information hiding) 或封裝 (encapsulation)。訊息隱藏可以讓模組間解耦 (decouple),讓模組能單獨開發、測試、修改及優化等等。
Java 在訊息隱藏上包含訪問機制 (access control) 決定 class 及其成員的可訪問性 (accessibility),關鍵字為 private、protected、public。規則是盡量讓每個 class 及其成員不被外界訪問,使用最低級別。
一般的 class 及介面有兩種級別:package-private 及 public。package-private 是不釋出的部份,而 public 為 API 使用者可以訪問的,所以必須維護其兼容性。如果一個 package-private class 只在某個 class 中使用,那可以考慮將它變成該 class 的 inner class,但整體上減少 public class 的訪問性,比上述還要重要。
下面列出 4 種級別,依序為存取性弱到強:
- private:只有該 class 內的成員可以存取。
- package-private (default):預設,同一 package 內的 class 皆能存取。
- protected:package 內的 class 可以存取,繼承該 class 的 subclass 亦能。
- public:任何 class 皆能存取。
在 public class 中的 field 絕對不能是 public 的,因為這樣會對該 field 失去控制權,調用者是有能力修改它的內容,但有例外就是用 public static final 來表示常數,該 field 應為基本數值或是不可變的引用。結論,設計上應盡量的降低所有成員的的可訪問性。
// Thing 陣列內的元素是有機會被修改的
public static final Thing[] VALUES = { ... };
// 兩種修改方式,將陣列宣告為 private 後提供可訪問的方法
private static final Thing[] PRIVATE_VALUES = { ... };
public static final List<Thing> VALUES =
Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));
public static final Thing[] values() {
return PRIVATE_VALUES.clone();
}
轉載請註明原文網址 https://cookieandcoketw.blogspot.com/2020/07/effective-java-15-class-accessibility.html
沒有留言:
張貼留言