列挙型を使った処理を共通化する (Java)
Javaで複数の列挙型(enum)に対して同じような処理を書く場合に、どのように共通化するかを考えました。この記事では、列挙型で共通のインターフェースを実装しても対処できないような場合について扱います。例えば、values()のようなstaticメソッドが関わる場合です。対象バージョンはJava SE 6です。(たぶん5でも動きます。)
2010/08/13追記
記事のタイトルを「列挙型を使った処理の共通化」から「列挙型を使った処理を共通化する」に変更しました。(前者だと、「『列挙型を使った処理』の共通化」と「列挙型を使った『処理の共通化』」のように2種類の解釈ができて紛らわしいため。)
共通化されていない場合
はじめに共通化されていない場合のコードを示します。main()を呼び出すと、2種類の列挙型(Size、Color)に対して、クラス名とメンバ一覧を出力します。printSizeValues()はSizeに対する出力処理、printColorValues()はColorに対する出力処理です。この2つのメソッドは、扱う型以外は全く同じです。
public class EnumTest1 { private enum Size {SMALL, MEDIUM, LARGE} private enum Color {BLUE, GREEN, RED, YELLOW, WHITE} public static void main(String[] args) { printSizeValues(); printColorValues(); } private static void printSizeValues() { System.out.println("[Size]"); for (Size size : Size.values()) { System.out.println(size.name()); } System.out.println(); } private static void printColorValues() { System.out.println("[Color]"); for (Color color : Color.values()) { System.out.println(color.name()); } System.out.println(); } }
実行結果は次のようになります。
[Size] SMALL MEDIUM LARGE [Color] BLUE GREEN RED YELLOW WHITE
Classオブジェクトを使った共通化
上記の「共通化されていない場合」のprintSizeValues()とprintColorValues()を共通化し、printEnumValues()というメソッドを作成しました。このコードの実行結果は、「共通化されていない場合」と全く同じです。
public class EnumTest2 { private enum Size {SMALL, MEDIUM, LARGE} private enum Color {BLUE, GREEN, RED, YELLOW, WHITE} public static void main(String[] args) { printEnumValues(Size.class); printEnumValues(Color.class); } private static void printEnumValues(Class<? extends Enum<?>> enumCls) { System.out.println("[" + enumCls.getSimpleName() + "]"); for (Enum<?> e : enumCls.getEnumConstants()) { System.out.println(e.name()); } System.out.println(); } }
補足
EnumSetオブジェクトを使った共通化
上記の「Classオブジェクトを使った共通化」とは別の方法で、「共通化されていない場合」の2つのメソッドを共通化しました。このコードの実行結果も、「共通化されていない場合」と全く同じです。
import java.util.EnumSet; public class EnumTest3 { private enum Size {SMALL, MEDIUM, LARGE} private enum Color {BLUE, GREEN, RED, YELLOW, WHITE} public static void main(String[] args) { printEnumValues(Size.class.getSimpleName(), EnumSet.allOf(Size.class)); printEnumValues(Color.class.getSimpleName(), EnumSet.allOf(Color.class)); } private static void printEnumValues(String enumName, EnumSet<?> es) { System.out.println("[" + enumName + "]"); for (Enum<?> e : es) { System.out.println(e.name()); } System.out.println(); } }
補足
- 共通メソッドの引数で、EnumSetオブジェクトを渡します。(厳密には「EnumSet<?>」です。)
- クラス名などのクラス自体の情報は、EnumSetオブジェクトとは別に渡す必要があります。*2
- 共通メソッドを呼び出す前に、EnumSetオブジェクトを編集することも可能です。(特定の値の追加・削除など)