【Effective Java】項目31:序数の代わりにインスタンスフィールドを利用する
ordinal() メソッド
enum は ordinal() というメソッドを持っています。 これは列挙宣言での位置を返すメソッドです。
public enum Week { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday; } Week.Sunday.ordinal(); // => 0 Week.Monday.ordinal(); // => 1 Week.Tuesday.ordinal(); // => 2 Week.Wednesday.ordinal(); // => 3 Week.Thursday.ordinal(); // => 4 Week.Friday.ordinal(); // => 5 Week.Saturday.ordinal(); // => 6
ordinal() で取得できる数を定数にひもづくデータとして使ってはいけません。
public enum Ensemble { SOLO, DUET, TRIO, QUARTET, QUINTET, SEXTET, SEPTET, OCTET, NONET, DECTET; // グループのメンバーの数を返す public int numberOfMusicians() { return ordinal() + 1; } }
上記の enum では、アンサンブルのメンバーの人数を ordinal() を使って実装しています。 この状態では上手く動きますが、今後の発展を考えると以下のような問題が生じます。
- 定数を並び替えるとメソッドが動作しなくなる
- 同じ数字を持つ定数(たとえば 8 人のミュージシャンがいるダブルカルテット)は割り当てられない
もともと、ordinal() は EnumSet や EnumMap など、enum に対するデータ構造を実装する手助けとして提供されています。 そのため、普通の開発者が ordinal() を使うことはほぼありません。
インスタンスフィールドを使う
ordinal() を使うのではなく、項目30で説明したインスタンスフィールドを使うべきです。
public enum Ensemble { SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUINTET(5), SEXTET(6), SEPTET(7), OCTET(8), DOUBLE_QUARTET(8), NONET(9), DECTET(10), TRIPLE_QUARTET(12); private final int size; Ensemble(int size) { this.size = size; } public int numberOfMusicians() { return this.size; } }
こうすることで、上述した問題はすべて解決されています。
感想
今回はたった1ページの項目だったのでまとめるのが楽だった。