Menu
Coddy logo textTech

関数型インターフェース

CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 39/87。

関数型インターフェースとは、抽象メソッドをただ1つだけ持つインターフェースのことです。この単一メソッドという制約により、関数型インターフェースはラムダ式を使用して実装できるようになり、より簡潔なコーディングスタイルが可能になるという特別な性質を持っています。

Javaは、インターフェースが関数型であることを明示的に示すために @FunctionalInterface アノテーションを提供しています。このアノテーションは任意ですが、誤って2つ目の抽象メソッドを追加した場合にコンパイラがエラーを検出するのに役立ちます:

@FunctionalInterface
public interface Calculator {
    int calculate(int a, int b);
}

関数型インターフェースは、クラスを使用した従来の方法、またはラムダ式を使用したより簡潔な方法で実装できます。

// 従来の実装
Calculator adder = new Calculator() {
    @Override
    public int calculate(int a, int b) {
        return a + b;
    }
};

// ラムダ式(より簡潔です!)
Calculator adder = (a, b) -> a + b;

System.out.println(adder.calculate(5, 3));  // 8

関数型インターフェースは、デフォルトメソッドやstaticメソッドを持つことができます。これらは単一抽象メソッドのルールにはカウントされないためです。Javaのjava.util.functionパッケージには、PredicateFunctionConsumerなど、ストリームやコレクションを扱う際によく遭遇する多くの組み込み関数型インターフェースが用意されています。

challenge icon

チャレンジ

簡単

関数型インターフェースとラムダ式を使用して、文字列変換システムを構築しましょう。単一の関数型インターフェースを活用して、文字列にさまざまな変換を適用できる柔軟なテキストプロセッサを作成します。

コードは以下の3つのファイルに分けて構成します:

  • StringTransformer.java: 任意の文字列変換操作を表す関数型インターフェースを定義します。関数型であることを保証するために、@FunctionalInterface アノテーションを付加してください。このインターフェースには、Stringを受け取りStringを返す transform という名前の抽象メソッドを1つだけ宣言する必要があります。
  • TextProcessor.java: 関数型インターフェースを使用してテキストを処理するクラスを作成します。このクラスは StringTransformer を保持するフィールドと、それを初期化するためのコンストラクタを持つ必要があります。また、指定されたテキストにトランスフォーマーを適用して結果を返す process(String text) というメソッドを含めてください。この設計により、コンストラクタを通じて任意の変換動作を注入できるようになります。
  • Main.java: ラムダ式を使用して異なる変換を作成し、すべてを統合します。2つの入力(テキスト文字列と操作タイプ(upperlower、または reverse))を受け取ります。

    操作タイプに基づいて、適切なラムダ式を持つ TextProcessor を作成します:

    • upper: テキストを大文字に変換します
    • lower: テキストを小文字に変換します
    • reverse: テキストを反転させます(ヒント:StringBuilder を使用してください)

    その後、入力テキストを指定して process() を呼び出し、結果を Result: [transformed text] という形式で出力します。

変換対象のテキスト(String)と操作タイプ(String)の2つの入力を受け取ります。

渡すラムダ式によって、同じ TextProcessor クラスがまったく異なる操作を実行できることに注目してください。これが関数型インターフェースの強力な点です!

チートシート

関数型インターフェースは、抽象メソッドを1つだけ持つインターフェースです。ラムダ式を使用して簡潔なコードで実装できます。

インターフェースを関数型としてマークするには、@FunctionalInterfaceアノテーションを使用します(任意ですが推奨されます):

@FunctionalInterface
public interface Calculator {
    int calculate(int a, int b);
}

関数型インターフェースは、従来の方法またはラムダ式で実装できます:

// 従来の実装
Calculator adder = new Calculator() {
    @Override
    public int calculate(int a, int b) {
        return a + b;
    }
};

// ラムダ式
Calculator adder = (a, b) -> a + b;

System.out.println(adder.calculate(5, 3));  // 8

関数型インターフェースは、単一抽象メソッドの規則に違反することなく、デフォルトメソッドや静的メソッドを持つことができます。

Javaのjava.util.functionパッケージには、PredicateFunctionConsumerなどの組み込み関数型インターフェースが用意されています。

自分で試してみよう

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String text = scanner.nextLine();
        String operation = scanner.nextLine();
        
        TextProcessor processor;
        
        // TODO: 操作タイプに基づいて、適切なラムダ式を使用してTextProcessorを作成します:
        // - "upper": テキストを大文字に変換
        // - "lower": テキストを小文字に変換
        // - "reverse": テキストを反転(ヒント:StringBuilderを使用)
        
        // TODO: 入力テキストを使用してprocess()を呼び出し、結果を出力します
        // 出力形式: "Result: [transformed text]"
    }
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン