本文へスキップ
BecomeCoder

Java MVVMコース · 第2章 Entity ― 業務データの核 · レッスン7

Priority ― 優先度を列挙で表す

ブラウザで完結

導入

優先度のように「決まった選択肢の中から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のままでよい

演習

契約どおりのPriorityLOWMEDIUMHIGH、それぞれ日本語のラベル「低」「中」「高」を持つ)を使い、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.javahigherを実装します。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 }はこの後の章でもそのまま使い続ける

次回: TaskTitlePriorityを組み込んで、TaskItemを契約どおりの最終形にします。

実際に動かしてみよう

このレッスンのサンプルは、実務と同じように役割ごとの .java ファイルへ分けてあります。下のエディタは最初からその複数ファイルが入った状態で、上のタブでファイルを切り替えられます。そのまま「▶ 実行」を押せば全ファイルをまとめて解釈して動かせます。@Test の付いたテストがあるレッスンでは、テストメソッドごとに ✅/❌ の一覧(Red/Green)が出るので、まずテストを赤くしてから実装で緑にする、というTDDの回し方をその場で体験できます(本物のJVMではなく、JUnit・Mockitoの主要な書き方まで再現した学習用シミュレータです)。

Java — ブラウザ内で実行(学習用シミュレータ)

Javaの教材サブセットを動かす学習用シミュレータを読み込みます(本物のJVMではなく、動きを再現した軽量な自作エンジンです)。
スクロールして表示された時点でも自動で読み込まれます。