11
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Javaで相関関係がある列挙型を定義する

Posted at

この記事はTumblrでも公開しています

はじめに

Javaの列挙型はメソッドを持つことはできますが、メソッド中で識別子による条件分岐処理を入れることは、列挙型の特徴を捉えておらず、また可読性の面であまりいい設計ではありません。

その問題を解消するための方法を忘備録としてメモします。

方法

例として、Colorという列挙型を考えます。Colorは、WHITE識別子の裏はBLACK、またBLACK識別子の裏はWHITEという相関関係を持ちます。

まず一番シンプルな列挙型は以下のようになります。

enum Color {
	WHITE, BLACK;
}

これに、WHITEの裏はBLACK、またBLACKの裏はWHITEという相関関係を定義するために以下のようにinverseメソッドを定義します。

enum Color {
	WHITE, BLACK;
	
	public Color inverse() {
		if (this == WHITE) {
			return BLACK;
		} else {
			return WHITE;
		}
	}
}

この書き方でも期待した動作はしますが、例えばコンストラクタを持たせた場合、列挙型Colorの性質を表す部分が分離して可読性が下がります。

そこでインスタンス変数とコンストラクタを用いて、以下のように設定しようとしました。

enum Color {
	WHITE(BLACK), BLACK(WHITE);

	public final Color inverse;
	Color(Color inverse) {
		this.inverse = inverse;
	}
}

しかし、これはコンパイルするとエラーがでます。

$ javac Color.java
Color.java:2: エラー: 前方参照が不正です
    WHITE(BLACK), BLACK(WHITE);
          ^
エラー1個

WHITEのコンストラクタが呼ばれた時に、まだ宣言されていないBLACKを参照していることが原因です。

これを解決するために、Color列挙型に抽象メソッドを宣言し、それぞれの識別子で独自関数としてオーバーライドしました。

enum Color {
    WHITE{
        @Override
        public Color inverse() {
      	     return BLACK;
        }
    },
    BLACK{
        @Override
        public Color inverse() {
            return WHITE;
        }
    };

    abstract Color inverse();
}

これによって今後の拡張をする際にも列挙型の性質を一つの部位に書くことができます。

まとめ

  • コンストラクタで相関関係を定義すると、前方参照のエラーが起きる。
  • 相関関係を定義するときには、抽象メソッドを識別仕事に独自関数としてオーバーライドして実現する。
11
8
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?