情報を隠蔽せよ
public Book { private String title; private int price; public Book(String title, int price) { this.title = title; this.price = price; } public String getTitle() { return name; } public int getPrice() { return price; } }
オブジェクト指向における「情報隠蔽」という考え方からすれば,クラスの実装について詳細を隠蔽するということは極めて重要です.
Book クラスのフィールド title と name の可視性は private ですので,一見すると情報隠蔽が達成されているように感じるかもしれません.
非公開フィールドに対する getter の存在
ところが,Book クラスには private フィールドを取得する getter として
getTitle と getPrice が定義されています.
せっかくフィールドを非公開にしたのに,これらの getter によってフィールドの情報が流出しています.
この例から,(完璧な)情報隠蔽のためには,次の2つの取り組みが必要だと分かります.
- フィールドは private にする
- getter (または,それに相当するメソッド)を定義しない
情報を隠蔽する目的とは何か
ところで,情報を隠蔽する目的とは何でしょうか?
このエントリでは,次の点に着目しようと思います.
- あるクラスは,そのクラスのフィールドを使った処理に責任をもつ
この観点から言えば,
先の例では本に関する処理が Book クラス以外でされると予想できます.
例えば,本の単価と個数から合計額を計算するとき
次のように main 関数でコーディングできちゃいます.
public Main { public static void main(String[] argv) { // ... int total = book.getPrice() * quantity; // ... } }
本に関する処理を(Book クラスの外の) main 関数でできてしまっては,
Book オブジェクトを作った意味がありません.
「フィールドは非公開」& 「getter もなし」バージョン
で,いい具合に書き換えると次のようになります.
public Book { private String title; private int price; public Book(String title, int price) { this.title = title; this.price = price; } public int (int quantity) { return price * quantity; } }
public Main { public static main(String[] argv) { // ... Book abook = new Book("六番目の小夜子", 578); int total = abook.calcTotal(2); // ... } }
本の値段は Book クラス自身だけが知っているため,
情報隠蔽が達成できました.
加えて,本の値段を Book クラスのメソッドで計算することで,
本に関する処理を Book クラスにまとめることができています.
誤解されないためにヒトコト
getter を絶対禁止とは言っていません.
ただ,本当に getter が必要かを考えることは
優れたデザインへの一歩だと思います.