0Pricing
Java Academy · レッスン

ネストした Record パターン

深くネストしたデータにマッチさせます。

「ネストした Record パターン」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。

ネストしたレコードパターン

レコードパターンはネストできます。レコードそのものであるコンポーネントを、外側のパターン内で分解できるのです。これにより、深く構造化されたデータにも1つの式でマッチできます。

ネストしたデータモデル

2つの Point レコードから構成される Line を考えてみましょう。内側のレコードは、ネストするのに適しています。

public class Main {
    record Point(int x, int y) {}
    record Line(Point start, Point end) {}

    public static void main(String[] args) {
        Line line = new Line(new Point(0, 0), new Point(3, 4));
        System.out.println(line);
    }
}

1レベルの分解

フラットなパターンでは、2つの Point コンポーネントを束縛しますが、それぞれ全体のまま扱います。

public class Main {
    record Point(int x, int y) {}
    record Line(Point start, Point end) {}

    public static void main(String[] args) {
        Object obj = new Line(new Point(0, 0), new Point(3, 4));
        if (obj instanceof Line(Point s, Point e)) {
            System.out.println(s + " -> " + e);
        }
    }
}

さらに深く分解する

内側の Point s をそれ自体のレコードパターンに置き換えると、座標に直接アクセスできます。Line(Point(int x1, int y1), Point(int x2, int y2)) のように記述します。

public class Main {
    record Point(int x, int y) {}
    record Line(Point start, Point end) {}

    public static void main(String[] args) {
        Object obj = new Line(new Point(0, 0), new Point(3, 4));
        if (obj instanceof Line(Point(int x1, int y1), Point(int x2, int y2))) {
            double len = Math.hypot(x2 - x1, y2 - y1);
            System.out.println("Length: " + len);
        }
    }
}

任意の深さに対応

ネストはデータの構造に応じて、必要な深さまで行えます。各レベルでコンポーネント全体を束縛するか、さらに分解するため、構造の形状を正確に反映できます。

public class Main {
    record Point(int x, int y) {}
    record Line(Point start, Point end) {}
    record Drawing(Line first, String label) {}

    public static void main(String[] args) {
        Object obj = new Drawing(new Line(new Point(1, 2), new Point(3, 4)), "diag");
        if (obj instanceof Drawing(Line(Point(var ax, var ay), var end), var label)) {
            System.out.println(label + " starts at " + ax + "," + ay);
            System.out.println("ends near " + end);
        }
    }
}

var と型の組み合わせ

ネストしたパターン内では、明示的な型と var を自由に組み合わせられます。そのまま渡すだけのコンポーネントには var を使い、明確さが必要な箇所では明示的な型を使いましょう。

switch でのネスト

ネストしたパターンは switch で特に表現力を発揮し、それぞれの case でデータの形状を正確に記述できます。

public class Main {
    record Point(int x, int y) {}
    record Line(Point start, Point end) {}

    static String describe(Object o) {
        return switch (o) {
            case Line(Point(var x1, var y1), Point(var x2, var y2)) when x1 == x2 -> "vertical";
            case Line(Point p1, Point p2) -> "general line";
            default -> "not a line";
        };
    }

    public static void main(String[] args) {
        System.out.println(describe(new Line(new Point(2, 0), new Point(2, 9))));
        System.out.println(describe(new Line(new Point(0, 0), new Point(5, 5))));
    }
}

全体がマッチする必要がある

ネストしたパターンは、すべてのレベルがマッチした場合にだけマッチします。いずれかのコンポーネントの型がサブパターンの想定と異なると、全体のマッチが失敗し、変数は1つも束縛されません。

可読性とのトレードオフ

深いネストは強力ですが、読みにくくなることがあります。パターンが大きくなりすぎた場合は、1レベルだけ分解し、残りは別のロジックで処理することを検討してください。

ネストした束縛に対するガード

ネストしたパターンでは内側の値がローカル変数として公開されるため、1つの when ガードから複数のレベルにあるフィールドを同時に参照できます。

public class Main {
    record Point(int x, int y) {}
    record Line(Point start, Point end) {}

    static boolean isUnitStep(Object o) {
        return o instanceof Line(Point(int x1, int y1), Point(int x2, int y2))
            && x2 - x1 == 1 && y2 - y1 == 1;
    }

    public static void main(String[] args) {
        System.out.println(isUnitStep(new Line(new Point(0, 0), new Point(1, 1))));
        System.out.println(isUnitStep(new Line(new Point(0, 0), new Point(2, 2))));
    }
}

完全な例

両端点を分解して、線分の中点を計算します。

public class Main {
    record Point(int x, int y) {}
    record Line(Point start, Point end) {}

    static Point midpoint(Object o) {
        if (o instanceof Line(Point(int x1, int y1), Point(int x2, int y2))) {
            return new Point((x1 + x2) / 2, (y1 + y2) / 2);
        }
        return null;
    }

    public static void main(String[] args) {
        System.out.println(midpoint(new Line(new Point(0, 0), new Point(4, 6))));
    }
}

理解度チェック

ネストしたレコードパターンの理解度を確認しましょう。

まとめ

ネストしたレコードパターンについて学びました。

  • レコードそのものであるレコードコンポーネントを、パターン内で直接分解できます。
  • 任意の深さまでネストでき、明示的な型と var を組み合わせられます。
  • すべてのレベルがマッチした場合にだけ、マッチは成功します。
  • 内側の束縛は、ガードと本体の両方で利用できます。

よくある質問

「ネストした Record パターン」レッスンは無料ですか?

はい。「ネストした Record パターン」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。

「ネストした Record パターン」で何を学びますか?

深くネストしたデータにマッチさせます。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Java Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「ネストした Record パターン」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このJava Academyレッスンでコードを書いて実行できますか?

はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. instanceof のパターンマッチング
  2. Record パターン
  3. ネストした Record パターン
  4. switch のパターン
← Java Academyに戻る