2017-08-18 7 views
11

は、いくつかのJava 8メソッド関数を考える:2つのアクセサの構図がどのように見えるJavaメソッドリファレンスを簡潔に記述する方法は?

class Foo { Bar getBar() {} } 
class Bar { Baz getBaz() {} } 

Function<Foo, Bar> getBarFromFoo = Foo::getBar; 
Function<Bar, Baz> getBazFromBar = Bar::getBaz; 
Function<Foo, Baz> getBazFromFoo = getBarFromFoo.andThen(getBazFromBar); 

より簡潔な方法はありますか?これはうまくいくようです

((Function<Foo, Bar>) Foo::getBar).andThen(Bar::getBaz) 

しかし、それはかなり醜いです。外側の括弧は優先順位の理由のために理にかなっていますが、なぜキャストが必要ですか?

Foo::getBar::getBazが...素敵な、悲しいかなだろう)

+0

のコンパイルに失敗します - > foo.getBarを():: getBaz' ?あなたはそれを過度に複雑にしているようです。私は行方不明のものがありますか? –

+2

@VinceEmigh、 'foo-> foo.getBar()。getBaz()'を意味しましたか?それ以外の場合は、意味がありません。 – Andrew

+0

@VinceEmigh、あなたが提案した方法は十分に柔軟ではありません。可能なすべてのケースを構築するのではなく、実行時に 'Function'の' compose'、 'andThen'のような簡単な操作でそれらを構成する単純なマッパー(' a-> b'、 'b-> c')コンパイル時に。 – Andrew

答えて

3

andThen()以外のJavaでの機能を構成する専用の方法はありません。

Foo::getBarがあいまいなので、キャストを実行する必要があります。 **これは、同様のメソッドシグネチャを持つすべてのインターフェイスと一致する可能性があります。

残念ながら、((Function<Foo, Bar>) Foo::getBar).andThen(Bar::getBaz)はあなたができる最善の方法です。

10

はのは、機能のインタフェースを定義してみましょう:

@FunctionalInterface 
interface MyFunctionalInterface { 
    Bar getBar(Foo f); 
} 

我々はは "Fooを取り、Bar戻る"を意味し、メソッド参照Foo::getBar

(Foo foo) -> foo.getBar(); 

を少し簡略化することができます。その説明については、メソッドの多くが適している(例えば、私たちのgetBarとのインタフェースとそのapplyFuntion<Foo, Bar>):

キャストが必要な理由の質問への答えである
MyFunctionalInterface f1 = (Foo foo) -> foo.getBar(); 
Function<Foo, Bar> f2 = (Foo foo) -> foo.getBar(); 


は、より簡潔な方法があるかどうかの質問に答えるために肯定的に、我々はコンテキストを設定する必要があります。文脈が明確で作業を続けることが私たちにFunctionを与える:

class Functions { 
    public static <I, O> Function<I, O> of(Function<I, O> function) { 
     return function; 
    } 
} 

Functions.of(Foo::getBar).andThen(Bar::getBaz); 
1

多分ちょうどラムダ式を使うのか?

x -> x.getBar().getBaz() 

タイプのあいまいさのために、既に提案した以外の機能を作成する方法はありません。これ以上はありませんFoo::getBar::getBaz

0

それはあなたが得ようとしている最高です。これがうまくいくと思うなら:

Foo::getBar::getBaz 

それはできません。Foo::getBarポリ式です - 使用されるコンテキストによって異なります - Functionでもかまいませんが、例えばPredicateでもかまいません。それは潜在的に多くのものに適用される可能性があるので、キャストはただそこに必要です。

連鎖を行うメソッドの背後にそれを隠すことができますが、andThenでも問題は残ります。

EDIT

ここでは例を参照してください:

public static void cool(Predicate<Integer> predicate) { 

} 

public static void cool(Function<Integer, String> function) { 

} 

をして表現cool(i -> "Test");は `FOOないのはなぜ

+0

ありがとうございます。私はそれが動作しないことを知っています。ちょっと欲しい...型推論は型がブール値を返さないため、述語ではないことを知っているはずです。私はJava型の推論ウィザードではありませんが、Foo :: getBarはフォームFoo-> BarとgetBazがBar-> Bazを満たすため、Foo :: getBar: :getBaz'はFoo-> Bazの形式の関数インタフェースを満たすポリ式です。 – Gene

+0

@Geneの 'Predicate'と' Function'は、これらが本当にポリ式であることを証明するための一例に過ぎません(editを参照)...そして、lambdaとメソッド参照の '型推論'それがおそらくこの連鎖がまったく実装されていなかった理由です - それは*まったく*些細ではない – Eugene

+0

私は実際に型推論を書いています。私はそれが自明ではないことを知っている。それが不可能というわけではありません。 – Gene

関連する問題