列挙型とは?
enum(イーナム)は、列挙型(enumeration type)を表すデータ型です。
使用用途は、特定の値(定数など)をまとめて管理する際に使用されます。
例えば、季節だったり、曜日だったり、特定の決まった値を使用する際に便利です。
利点については、後述しますが、
1番の利点は複数人で開発を行う場合の認識合わせが楽になることだと思います。
例えば、この人は「SPRING」と書いているのに、この人は「Spring」と書いていて、
条件分岐の判定結果が思い通りにならないなど。。。
enumは非常に便利なので、使い方を覚えると手放せなくなります。
基本的な使い方
下記は、enumの基本的な構文です。
基本的には、使用したい文字をカンマ区切りで宣言します。
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
}
この例では、曜日をまとめています。
呼び出し方は、下記の通りです。
public class Main {
public static void main(String[] args) {
Day day = Day.SUNDAY;
System.out.println(Day.SUNDAY);
// SUNDAY
}
}
上記のように、「enum名.値」で対象が取得できます。
enumはswitch文と相性が良いので、下記ではswitch文を使用したサンプルコードを紹介します。
※enumは「Day.java」を使用しています。
public class Main {
public static void main(String[] args) {
Day today = Day.FRIDAY;
switch (today) {
case MONDAY:
System.out.println("今日は週初めです");
break;
case FRIDAY:
System.out.println("今日は週末です");
break;
case SATURDAY:
case SUNDAY:
System.out.println("今日は休みです");
break;
default:
System.out.println("普通の平日です");
break;
}
}
}
// 今日は週末です
enumの利点
enumには様々な利点があります。
その中でも特に優れた点について解説します。
型安全を保証
1つ目は型安全にできる点です。
冒頭でも記載しましたが、
enumは開発者によって生じる小さな認識齟齬を未然に防ぐことができます。
その他にも、Javaが提供する型システムの一部であるため、
コンパイル時点で型の不一致によるエラーを防ぐことができます。
よって、想定外の値が混入する可能性を無くすことができ、安全性が向上します。
個人で開発している人でも、プログラムの修正を久しぶりにするときなど、
どのように定義したか、わざわざ調べる必要がないのでメリットはあります。
可読性の向上
enumを使用することで、大幅に可読性が向上します。
enumは、値が分かりやすい(例えば、上記のSUNDAYなどの曜日)ため、
プロジェクトに途中から参加した人が読んでも、難なく理解ができます。
こういった点から、可読性の向上にenumは使用すべきだと考えます。(個人開発でも)
ただし、統一感がない場合は、enumの良さが皆無になるので気を付けましょう。
そのため、enum名や値を決めるときは、チームメンバーと話し合って決めると良いと思います。
クラスの機能を持つ
enumはクラスの機能を持っています。
そのため、フィールドやメソッドの定義が可能です。
応用次第で、より便利なenumを作成することができるようになります。
また、関連性の高いメソッドをenumに作成することで、
わざわざ別クラスから呼び出さなくても良くなるため、可読性も向上します。
メソッドについては、以下の記事でも紹介していますので、参考までに。
高度な使用方法
enumは、クラスの機能を持っているため、
フィールドやメソッド、コンストラクタを使って、下記のように記述できます。
public enum Season {
SPRING("Spring"),
SUMMER("Summer"),
AUTUMN("Autumn"),
WINTER("Winter");
// フィールドの定義
private String seasonName;
// コンストラクタの定義
Season(String seasonName) {
this.seasonName = seasonName;
}
// 値取得用メソッド
public String getSeasonName() {
return this.seasonName;
}
}
値の取得は、下記のように記述します。
public class Main {
public static void main(String[] args) {
Season season = Season.SUMMER;
System.out.println(season); // SUMMER
}
}
もう少し、応用的な使い方をしてみます。
下記のコードはenum定数がexec()というメソッドを持っている例です。
public enum Calc {
ADD {
@Override
public int exec(int val1, int val2) {
return val1 + val2;
}
},
SUBTRACT {
@Override
public int exec(int val1, int val2) {
return val1 - val2;
}
},
MULTIPLY {
@Override
public int exec(int val1, int val2) {
return val1 * val2;
}
},
DIVIDE {
@Override
public int exec(int val1, int val2) {
if (val2 == 0) {
throw new IllegalArgumentException("Cannot divide by zero");
}
return val1 / val2;
}
};
// 抽象メソッドの定義
public abstract int exec(int val1, int val2);
}
値の取得方法は、下記の通りです。
public class Main {
public static void main(String[] args) {
Calc calc = Calc.ADD;
System.out.println(calc.exec(5, 5)); // 10
System.out.println(Calc.MULTIPLY.exec(3, 6)); // 18
}
}
enumは上記のような応用的な使い方もできるため、
使い方次第で無限大の可能性を秘めています。
実践的サンプルコード
次は、より実践的なサンプルコードを紹介します。
ホテルのプランを定義しているenumを作成して、
プランの詳細を出力するプログラムを作ってみます。
まずは、プラン情報を持るenumを作成します。
public enum Plan {
LUXURY("ラグジュアリー", 45000),
STANDARD("スタンダード", 20000),
ECONOMY("エコノミー", 10000);
private String planName;
private int price;
Plan(String planName, int price) {
this.planName = planName;
this.price = price;
}
public String getPlanName() {
return this.planName;
}
public int getPrice() {
return this.price;
}
}
次に、注文用のメソッドを持つクラスを作成します。
別クラスに分けた理由は後述します。
public class Order {
public static void planOrder(Plan plan) {
System.out.println("予約プラン:" + plan.getPlanName());
System.out.println("価格:" + plan.getPrice());
}
}
最後に、呼び出し用のMainクラスを作成して、ラグジュアリープランを予約してみます。
public class Main {
public static void main(String[] args) {
Order.planOrder(Plan.LUXURY);
// 予約プラン:ラグジュアリー
// 価格:45000
}
}
最後に、注文用のメソッドを別クラスに分けた理由についてです。
理由としては、役割の分離をした設計をするためです。
役割の分離を明確に行うことで、再利用性が高まり、開発効率も上がります。
このような設計原則を「Separation of Concerns」と呼びます。
最後に
enumは、非常に便利で、可読性の向上や型安全な設計など利点がかなりあります。
また、使い方次第で紹介したサンプルコードを超える便利な使い方ができる可能性を秘めています。
さらに勉強したい方は、書籍を買って勉強するのも良いと思います。
コメント