導入
優先度のように「決まった選択肢の中から1つを選ぶ」種類の値は、TaskTitleほど複雑な検証ロジックを必要としないことが多く、Javaの**enum**でシンプルに表現できます。enum定数は宣言順にordinal()(0始まりの通し番号)を持つので、宣言順を工夫するとordinal()の比較で大小関係も表現できます。
説明
flowchart LR
L["LOW(ordinal=0)"] --> M["MEDIUM(ordinal=1)"] --> H["HIGH(ordinal=2)"]
サンプル
public enum Rank {
BRONZE, SILVER, GOLD
}
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class RankTest {
@Test
void sengenJun_GaDaishoKankeiNiNaru() {
Rank r1 = Rank.BRONZE;
Rank r2 = Rank.GOLD;
assertTrue(r2.ordinal() > r1.ordinal(), "宣言順が大小関係になる(GOLDの方がordinal()が大きい)");
}
}
enum定数は宣言順に0, 1, 2, ...というordinal()を持つordinal()同士を比べれば大小関係が表現できる(大きいほど後に宣言されている)。追加のクラスを作る必要はない- 選択肢が増減しても、呼び出し側のコードは
ordinal()の比較やswitchのままでよい
演習
契約どおりのPriority(LOW・MEDIUM・HIGH、それぞれ日本語のラベル「低」「中」「高」を持つ)を使い、2つのうち優先度が高い方を返す関数をTDDで実装します。PriorityそのものはPriority.javaに、比較ロジックとテストはPriorityTest.javaに分けて書きましょう。
public enum Priority {
LOW("低"), MEDIUM("中"), HIGH("高");
private final String label;
Priority(String label) {
this.label = label;
}
public String getLabel() { return label; }
}
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class PriorityTest {
// TODO: 2つのPriorityのうち高い方を返す higher を実装してください(ordinal()が使えます)
static Priority higher(Priority a, Priority b) {
return null;
}
@Test
void highNoHoga_YusenIdoGaTakai() {
assertEquals(Priority.HIGH, higher(Priority.LOW, Priority.HIGH), "HIGHの方が優先度が高い");
}
@Test
void mediumNoHoga_LowYoriTakai() {
assertEquals(Priority.MEDIUM, higher(Priority.MEDIUM, Priority.LOW), "MEDIUMの方が優先度が高い");
}
@Test
void onajiNaraOnajiAtaiDeYoi() {
assertEquals(Priority.MEDIUM, higher(Priority.MEDIUM, Priority.MEDIUM), "同じなら同じ値でよい");
}
@Test
void labelHaNihongo() {
assertEquals("高", Priority.HIGH.getLabel(), "HIGHのラベルは「高」");
}
}
- 期待される結果: 4件のテストがすべて成功
ヒント1を見る
PriorityTest.javaのhigherを実装します。static Priority higher(Priority a, Priority b) { return a.ordinal() > b.ordinal() ? a : b; }
ヒント2を見る
enumは宣言順にordinal()を持ちます。Priority.LOW.ordinal()は0、Priority.HIGH.ordinal()は2です
まとめ
- 決まった選択肢から1つを選ぶ値は
enumで十分なことが多い enum定数は宣言順にordinal()を持ち、その比較で大小を表現できるenumはコンストラクタとgetLabel()のようなメソッドを持てる。Priority { LOW, MEDIUM, HIGH }はこの後の章でもそのまま使い続ける
次回: TaskTitleとPriorityを組み込んで、TaskItemを契約どおりの最終形にします。