Enumと定数の差

についていろいろな知見を得たのでメモしておく。

ことの発端

発端はこちら。

もう少し詳しく言うと、

こうなる。Enumについて解説しようと思ったところ、ふと「定数と何が違うんだろう?」と思ったのがきっかけです。いつもご意見ありがとうございます。

Enumと定数の違い

簡単に言うと、値が取りうる範囲をどこで保証するかという点が違う。

定数クラスの場合

定数だけを持つクラスを宣言したとする。こんな感じ。

public class BloodType {
    public static final int A = 1;
    public static final int B = 2;
    public static final int O = 3;
    public static final int AB = 4;

    private BloodType(){} // インスタンス化防止
}

でも、BloodTypeを受け取るメソッドというのは引数をint型にせざるを得ない。

public int hogeMethod(int bloodType){
    return 0; // 実際には血液型に応じて何かするメソッド
}

これだと、引数のbloodTypeがA,B,O,ABの4つのうちどれかであることを保証するのは実装した人になる。if文で分岐するなり、switch文を書くなりして、elseなりdefaultでどうするか(nullを返すとか、例外投げるとか、デフォルト値的なものを返すとか)を考えなきゃいけない。呼び出す側も、取りうる値を確認する必要がある。BloodTypeクラスの定義を確認して、A型なら1を入れることを知らなければならない。全然関係ない値を入れて「思った通りに動かないじゃん!」と言うこともできちゃう。困る。

Enumの場合

Enumで宣言すると、取りうる値の範囲を保証するのはコンパイラになる。

public enum BloodType {
    A,B,O,AB
}

こうすると、BloodTypeの取りうる値が4種類に限定される。呼び出す側も、BloodTypeまでタイプすれば候補の4つが予測変換?に表示されるからいちいち定義を見なくていいし、関係ない値を渡そうとするとコンパイルエラーになる。引数に取る側も、違う値が来たらどうしよう...と悩む必要がない。とても便利。

雑感

書いてみるとこれだけのことなんだけれど、意外とするするっと説明できなかった。選択肢?はいはいEnumね~わかるわかる、でなんとなく過ごしていたのかもしれない。自分で説明しようとすると、これがわからない・あれどういう理由だっけ...?となるので、理解を試すためには自分が説明できるかを基準にすることはいいと思う。

というか「わかったふり」って自分も騙せるから怖いなぁ。こういう風に「なんとなくわかってるけどほんとはわからないこと」がたくさんあるんだろうと思うとちょっと怖い。