関数型インターフェース
CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 39/87。
functional interface とは、abstract method をちょうど 1 つ含む interface です。この単一の method という制約により、functional interface は特別なものとなります。これは lambda expressions を使って実装でき、より簡潔なコーディングスタイルを可能にするためです。
Java では、インターフェースを関数型として明示的に示すために @FunctionalInterface annotation が用意されています。この annotation は省略可能ですが、誤って 2 つ目の abstract method を追加した場合に、コンパイラーがエラーを検出するのに役立ちます。
@FunctionalInterface
public interface Calculator {
int calculate(int a, int b);
}functional interface を従来の方法で class を使って実装することも、lambda expression を使ってより簡潔に実装することもできます:
// 従来の実装
Calculator adder = new Calculator() {
@Override
public int calculate(int a, int b) {
return a + b;
}
};
// Lambda expression (much shorter!)
Calculator adder = (a, b) -> a + b;
System.out.println(adder.calculate(5, 3)); // 8関数型インターフェースには、デフォルトメソッドや静的メソッドを持たせることもできます。これらは単一抽象メソッドの規則には数えられないためです。Java の java.util.function パッケージには、ストリームやコレクションを扱う際によく使う Predicate、Function、Consumer など、多くの組み込み関数型インターフェースが用意されています。
チャレンジ
簡単functional interface と lambda expressions を使用して、文字列変換システムを構築しましょう。単一の functional interface によってすべてが動作する、文字列にさまざまな変換を適用できる柔軟なテキストプロセッサを create します。
コードを3つのファイルに整理します。
StringTransformer.java:任意の文字列変換 operation を表す functional interface を Define します。@FunctionalInterfaceannotation を付けて、functional な状態を維持できるようにします。interface には、String を受け取り String を返す、transformという単一の abstract method を Declare します。TextProcessor.java:functional interface を使用してテキストを process する class を Create します。StringTransformerを hold する field と、それを初期化する constructor を持たせます。指定されたテキストに transformer を適用して結果を返す、process(String text)という method を含めます。この設計により、constructor を通じて任意の変換動作を注入できます。Main.java:lambda expressions を使用してさまざまな変換を create し、すべてを組み合わせます。2つの input、つまりテキスト文字列と operation type(upper、lower、またはreverse)を受け取ります。operation type に Based して、適切な lambda を使用した
TextProcessorを create します。upper:テキストを大文字に変換しますlower:テキストを小文字に変換しますreverse:テキストを反転します(hint:StringBuilderを使用します)
次に、入力テキストを指定して
process()を Call し、次の format で結果を print します:Result: [transformed text]
2つの input、つまり変換するテキスト(String)と operation type(String)を受け取ります。
渡す lambda によって、同じ TextProcessor class が完全に異なる operation を実行できることに注目してください。これが functional interfaces の力です。
自分で試してみよう
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]"
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4継承
継承の基本 (extends)super キーワードメソッドのオーバーライド (@Override)コンストラクタチェーンObject クラス単一継承と多段階継承なぜ多重継承ができないのかまとめ:従業員の階層構造6インターフェースと抽象クラス
インターフェース入門インターフェースの実装複数インターフェースの実装インターフェースのデフォルトと静的メソッド抽象クラス vs インターフェース関数型インターフェースまとめ - 決済システム自分で練習してみよう: Javaオンラインコンパイラ