2017-01-17 3 views
5

私はlamdbasを​​使用していますので、3つの異なるオブジェクトから取得できる値に従って、ModelObjectのプロパティを一貫して設定できます。私はbar(model::setB, bObject)bar(value -> model.setB(value), bObject);を書き換えることが可能であることをhere読んだ2つのパラメータを持つメソッドでのコロンの代入を

public class Processor { 

    private void bar(Setter setter, MyClass myObject) { 
     String variable = myObject.getStringByABunchOfMethods(); 
     setter.setVariable(variable); 
    } 

    protected void foo(...) { 
     ... 
     bar(value -> model.setA(CONSTANT, value), aObject); 
     bar(value -> model.setB(value), bObject); 
     bar(value -> model.setC(value), cObject); 
     ... 
    } 

    private interface Setter { 
     public void setVariable(String string); 
    } 

} 

public interface IModel { 
    public void setA(String arg0, String arg1); 
    public void setB(String arg0); 
    public void setC(String arg0); 
} 

:コードは次のように動作します。私はこれがより良く、より簡潔に見えると思いますが、setAメソッドをdouble ::の表記法に書き換える方法は見つかりませんでした。これが可能かどうか誰にでも教えてもらえますか?もしそうなら、これはどうですか?

+2

[メソッド参照リンク](https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html)を参照してください。あらゆる種類のメソッド参照を表示します。これが役に立ったらいいですか –

+0

私はそれが可能ではないと思います。 – toongeorges

答えて

5

https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.htmlhttps://www.codementor.io/eh3rrera/tutorials/using-java-8-method-reference-du10866vx

からメソッド参照の4つの異なる種類が存在します。対応ラムダと方法参照:

  • (引数) - > Class.staticMethod(引数)、クラス:: staticMethod
  • (OBJ、引数) - > obj.instanceMethod(引数)のObjectType :: instanceMethod
  • (引数) - > obj.instanceMethod(引数)、OBJ :: instanceMethod
  • (引数) - >新しいクラス名(引数)、クラス名::新しい

ラムダ値 - >モデル.setA(定数、値)はn上記のラムダのいずれかに対応しているため、メソッド参照として再記述することはできません。

+0

私はこの答えを受け入れた理由は、他の答えは賢明で便利なものですが、私のコードを理解しやすくしたり、きれいにするものでもありません。だから、 ' - >'表記を使うことに固執します。 –

2

Setter機能インターフェイスが書かれている方法ではありません。 setBおよびsetCとは異なり、setAメソッドでは2つの引数が必要ですが、Setterでは1つの引数しか必要としません。次の2つの引数を受け入れ、別のインターフェイスを追加することができます。

private interface SetterWithDefault { 
    public void setVariable(String defaultString, String string); 
} 

次にあなたがbarメソッドを経由して、それを呼び出すことができます。

private void bar(SetterWithDefault setter, String defaultString, MyClass myObject) { 
    String variable = myObject.getStringByABunchOfMethods(); 
    setter.setVariable(defaultString, variable); 
} 

次のように次に、あなたがbarを呼び出すことができます。

bar(model::setA, CONSTANT, aObject); 

注:barの方法をそのまま使用できます。新しいものは過負荷になる可能性があります。

+0

しかし、他の 'bar'コールは' OP 'が 'CONSTANT'パラメータなしでリストアップされていると何をすべきですか? – Sweeper

+1

@Sweeper彼は他の 'bar'メソッドを保つことができます。それは単純にオーバーロードされたメソッドです。 – manouti

4

2重コロン表記を使用するには、参照しているメソッドに、必要なメソッドと同じ署名が必要です。あなたが変更しない限り、あなたが::を使用することはできませんあなたのIModel:あなたはIModelsetAの過負荷を追加することができます

bar(model::setA, aObject); 

default void setA(String arg0) { 
    setA(CONSTANT, arg0); 
} 

次に、あなたがその過負荷を参照することができます。

+0

この場合、より洗練された表記法を使用するには、 'IModel'を変更することが多すぎるでしょう。私は前に 'default'キーワードを見たことがなかったので、私は将来についてそれを調べます! –

2

setBConsumer<String>で、setABiConsumer<String, String>です。その後、適応することができますBiConsumerConsumerへ:あなたのインタフェースのデフォルトの方法で

のどちらか(setA場合は常に一定と呼ばれ、なぜいけないのでしょうか?):

interface Model { 
    public void setA(String arg0, String arg1); 
    default void setA(String arg1) {setA(CONSTANT, arg1);} 
    public void setB(String arg0); 
    public void setC(String arg0); 
} 

どちらかBiConsumerのアダプタを使用してConsumerへ:

static <T, U> Consumer<V> adapt(T t, BiConsumer<T, U> biConsumer) { 
    Objects.requireNonNull(biConsumer, "biConsumer"); 
    Objects.requireNonNull(t, "t"); 
    return t -> biConsummer.accept(t, u); 
} 

そして、このようにそれを使用して:

protected void foo(...) { 
    ... 
    bar(adapt(CONSTANT, model::setA), aObject); 
    bar(model::setB, bObject); 
    bar(model::setC, cObject); 
    ... 
} 

注:私は例の名前としてadaptを使用し、それはあなたが(理由はジェネリックやタイプ消去の)他のadaptオーバーロードメソッドでそれを混ぜる悪い名前です。私は個人的にはfixLeftValueのような名前です。

adaptは、fooを呼び出すたびに生成されることに注意してください。

関連する問題