web-dev-qa-db-ja.com

機能インターフェイスとしての抽象クラス

Java 8では、抽象メソッドが1つしかない抽象クラスは関数型インターフェースではありません( JSR 335 )。

このinterfaceは機能的なインターフェースです。

public interface MyFunctionalInterface {
    public abstract void myAbstractMethod();
    public default void method() {
        myAbstractMethod();
    }
}

しかしこれは abstract class ではありません:

public abstract class MyFunctionalAbstractClass {
    public abstract void myAbstractMethod();
    public void method() {
        myAbstractMethod();
    }
}

したがって、抽象クラスをラムダ式とメソッド参照のターゲットとして使用することはできません。

public class Lambdas {
    public static void main(String[] args) {
        MyFunctionalAbstractClass functionalAbstractClass = () -> {};
    }
}

コンパイルエラーは次のとおりです。The target type of this expression must be a functional interface

言語設計者がこの制限を課したのはなぜですか?

36
gontard

これは、ラムダプロジェクトの開始当初から重要なトピックであり、多くの考えを集めてきました。チーフJava言語アーキテクトであるBrianGoetzは、ラムダのビューをobjectではなくfunctionとして強くサポートしています。引用:

Javaは、より機能的なスタイルのプログラミングを奨励することが最善の方向であると私は信じています。Lambdaの役割は、主に、より機能的なライブラリの開発と消費をサポートすることです。

私はJavaの将来について楽観的ですが、前進するために、いくつかの快適なアイデアを手放さなければならないことがあります。 Lambdas-are-functionsが扉を開きます。 Lambdas-are-objectsはそれらを閉じます。私たちはそれらのドアが開いたままになっているのを見たいと思っています。

ここ は引用の出典へのリンクであり、 ここ はブライアンの最近の投稿であり、同じ哲学的な点を繰り返し、追加のより実用的な議論でそれらを再確認しています。

モデルを単純化すると、あらゆる種類のVM最適化への扉が開かれます。(ここではアイデンティティのジェティソンが重要です。)関数は値です。オブジェクトとしてモデル化すると、必要以上に重く、複雑になります。あります。

このユースケースをバスの下に投げる前に、いくつかのコーパス分析を行って、インターフェイスSAMと比較して抽象クラスSAMが使用される頻度を見つけました。そのコーパスでは、ラムダ候補の内部クラスインスタンスの3%のみがターゲットとして抽象クラスを持っていることがわかりました。そして、それらのほとんどは、インターフェースを対象としたラムダを受け入れるコンストラクター/ファクトリーを追加する単純なリファクタリングに適していました。

33
Marko Topolnik