2011年4月5日火曜日

AnnotationとenumとInterface

プログラミングを始めると、いつもメタプログラミングなことを始めてしまって、
成果がよくないことがあるのですが…

これもその一例…

でも、意外とやってみて使えそうな気がしたのでメモです。

Javaのenumは何気にInterfaceの実装を記述することができて、
switch - case文でやっていることをそのままenumにさせることが可能だったりする。

以下はswitch文を使った例

public enum Fruit {
    APPLE, ORANGE
}

public class DisplayFruit {
    public void printFruitName(Fruit fruit){
        switch(fruit){
        case APPLE:
            System.out.println("This is an apple.");
            break;
        case ORANGE:
            System.out.println("This is an orange.");
            break;
        }
    }
}


このDisplayFruitクラスのユーザーはprintFruitNameメソッドに
enum Fruitを引数として渡して、
その結果としてそれぞれのフルーツの名前が表示される。

という仕様になっているわけですが、
これまたテストするのが面倒くさいなと思うわけですよ。

テストケースは二つで、
  • FruitAPPLEだった場合、This is an apple.と表示されること。
  • FruitORANGEだった場合、This is an orange.と表示されること。

これって、どうやんの?と思う。
いや、すくなくともオレだけは。

というわけで、
Javaのenumは何気にInterfaceの実装を記述することができる
を活用してみる。

まずはインターフェース。

public interface FruitName {
    public String getName();
}


で、次にenum。

public enum Fruit implements FruitName {
    APPLE{
        @Override
        public String getName(){
            return "This is an apple";
        }
    },
    ORANGE{
        @Override
        public String getName(){
            return "This is an orange";
        }
    }
}


こうすると、DisplayFruitはこんなになる。

public class DisplayFruit {
    public void printFruitName(Fruit fruit){
        System.out.println(fruit.getName());
    }
}


これでDisplayFruitのテストはほぼ無くなる。

で、最後にテストをする余地があるとしたら、それはDisplayFruitに対してのテストではなく、
Fruitに対するテストだけになる。

テストコードはこんな感じです。

public class FruitTest{
    @Test
    public void testGetName(){
        assertThat(Fruit.APPLE.getName(), is("This is an apple."));
        assertThat(Fruit.APPLE.getName(), is("This is an orange."));
    }
}


ただし、どっちのほうが性能が良いんだ?とかいう野暮な質問はオレにはしないでくれよ。

…答えられない人ノ

0 件のコメント:

コメントを投稿