2011年12月7日

定数インタフェース

よく定数クラスを作成しますが、定数をインタフェースに定義するソースを見ました。

/**
 * メッセージIDのインタフェース
 */
public interface MessageConstant {

    /**
     * システムエラーメッセージID
     */
    public static String SYSTEM_ERROR = "E-001";

    /**
     * 警告メッセージID
     */
    public static String WARN = "W-002";

}

以前見たときは、定数クラスだとインスタンス化されてしまう可能性があるためにインタフェースとしているかと思っていましたが、どうやら違いました。

public class Hoge implements MessageConstant {
    (略)
}

こういった感じでimplementしていました。

意味がわからないと思いましたが、こうやることで、クラス名で修飾しなくても、定数を使用できることに気がつきました。

定数インタフェースをimplementした場合
if (SYSTEM_ERROR.equals(id)) {
        // 何かの処理
    }

定数インタフェースをimplementしない場合
if (MessageConstant.SYSTEM_ERROR.equals(id)) {
        // 何かの処理
    }

これをやりたいのなら、定数クラスを作成して、コンストラクタをprivateにし、修飾したくないのならば、static importを使用すればいいと思います。

さらにインタフェースを実装してるのでこのような変なコーディングもできてしまいます。

Hoge hoge = new Hoge();
    MessageConstant hoge2 = (MessageConstant) hoge;    // 定数インタフェースにキャスト?

Hogeクラスのサブクラスでこのような実装を行っているとMessageConstantが不要になっても、HogeクラスがMessageConstantの実装を外すことができません。

そんなわけで、interfaceを定数に使うのはやめましょう。(そしてそれをimplementsすることをやめましょう)