私は 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"));
}
}
_
違いは、インターフェイスを実装するクラスである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();
問題
メソッドgrow
はパラメーターを取らないため、コンパイルエラーが発生します。
説明
ラムダ_() -> System.out.println("This from Lambda expression")
_自体は、Plant
(Eucalyptus
*ではない)インスタンスを表すことができます。
_Plant plant = () -> System.out.println("This from Lambda expression");
_
Plant
インターフェイスからラムダ式を作成し、print _"This was running from Lambda expression"
_によってオーバーライドgrow()
methodを試してください。
ここで少し誤解があります。ラムダは想定されていませんメソッドをオーバーライドする、 _@FunctionalInterface
_ タイプに基づいてメソッドを提供するまでです。
* Eucalyptus
オブジェクトをラムダで定義すると、ラムダがどのメソッドを表すかが曖昧で不明確になります。したがって、禁止されています (単一の抽象メソッドを持つ抽象クラスの場合でも)
ラムダ式の使用はここでは正しくありません。
インターフェイスを実装するには、ラムダ式を使用します。この場合、ラムダ式でそのインターフェイスのメソッドを呼び出すのではなく、ラムダ式を使用してPlant
の実装を提供します。
これは通常の使用法です:
Plant eucalyptus1 = () -> System.out.println("This from Lambda expression");
eucalyptus1.grow(); // Prints "This from Lambda expression"
言い換えると、機能的なインターフェースを持っているので、それを実装するクラス(匿名かどうか)の作成を回避できるはずです。
したがって、Eucalyptus
クラスを作成する必要はまったくありません。