web-dev-qa-db-ja.com

JavaメソッドはLambda式では適用できません

私は https://caveofprogramming.com/Java/whats-new-in-Java-8-lambda-expressions.html を見て読みましたが、ランナーオブジェクトに対して行ったのと同じパターンに従います。正常に動作します。

_Runner runner = new Runner();
runner.run(() -> System.out.println("Print from Lambda expression"));
_

次に、単純なインターフェースとクラスを作成して、学んだことを適用しようとします。匿名クラスをラムダ式に置き換えたいだけです。私の理解は、ラムダ式は匿名クラスの短いコードであり、読みやすさを向上させることです。

そのため、_eucalyptus1_という別のインスタンスを開始して_@Override_ grow()メソッドを試してみましたが、IDEエラーメッセージが表示されました:

_com.smith.Eucalyptus_のgrow()を_(lambda expression)_に適用することはできません

私がここで誤解していることを誰かが指摘してもらえますか?

コードは以下のとおりです。

_// a simple interface
interface Plant {
    public void grow();
}

// apply interface to class
class Eucalyptus implements Plant {
    @Override
    public void grow() {
        System.out.println("This is from Eucalyptus");
    }
}

public class Main {
    public static void main(String[] args) {

        // Create an instance of Eucalyptus
        Eucalyptus eucalyptus = new Eucalyptus();
        eucalyptus.grow();

        // Anonymous class Myrtle from Plant interface
        Plant myrtle = new Plant() {
            @Override
            public void grow() {
                System.out.println("This was running from anonymous class from Plant Interface");
            }
        };

        myrtle.grow();

        // Try to create a lambda expression from Plant interface
        // and override grow() method
        // by print ("This was running from Lambda expression")

        // this won't work. why?
        Eucalyptus eucalyptus1 = new Eucalyptus();
        eucalyptus1.grow(() -> System.out.println("This from Lambda expression"));
    }
}
_
11
Smith Lo

違いは、インターフェイスを実装するクラスであるEucalyptusの実装をオーバーライドしようとしていることです。

Eucalyptus eucalyptus1 = new Eucalyptus();
eucalyptus1.grow(() -> System.out.println("This from Lambda expression")); 
^__  // you cannot override a method using an instance of a class which is just an implementation of the interface

ラムダパラメータを渡すだけで終わり、もちろん、その定義に引数がないメソッドは、メソッドの呼び出し時に指定された場合、コンパイルされません。


代わりに、ラムダの実装方法を次のように比較できます。

//Anonymous class Myrtle from Plant interface
Plant myrtle = new Plant() {
          @Override
          public void grow() {
               System.out.println("This was running from anonymous class from Plant Interface");
          }
};
myrtle.grow();

ラムダ表現として表すことができます:

Plant lambdaRep =  () -> System.out.println("This is running via lambda from Plant Interface");
lambdaRep.grow();
10
Naman

問題

メソッドgrowはパラメーターを取らないため、コンパイルエラーが発生します。

説明

ラムダ_() -> System.out.println("This from Lambda expression")_自体は、PlantEucalyptus *ではない)インスタンスを表すことができます。

_Plant plant = () -> System.out.println("This from Lambda expression");
_

Plantインターフェイスからラムダ式を作成し、print _"This was running from Lambda expression"_によってオーバーライドgrow() methodを試してください。

ここで少し誤解があります。ラムダは想定されていませんメソッドをオーバーライドする_@FunctionalInterface_ タイプに基づいてメソッドを提供するまでです。


* Eucalyptusオブジェクトをラムダで定義すると、ラムダがどのメソッドを表すかが曖昧で不明確になります。したがって、禁止されています (単一の抽象メソッドを持つ抽象クラスの場合でも)

10
Andrew Tobilko

ラムダ式の使用はここでは正しくありません。

インターフェイスを実装するには、ラムダ式を使用します。この場合、ラムダ式でそのインターフェイスのメソッドを呼び出すのではなく、ラムダ式を使用してPlantの実装を提供します。

これは通常の使用法です:

Plant eucalyptus1 = () -> System.out.println("This from Lambda expression");
eucalyptus1.grow(); // Prints "This from Lambda expression"

言い換えると、機能的なインターフェースを持っているので、それを実装するクラス(匿名かどうか)の作成を回避できるはずです。

したがって、Eucalyptusクラスを作成する必要はまったくありません。

7
ernest_k