2017-08-16 6 views
0

あるパラメータを作成し、どのように私は次の操作を行います:JavaとScalaで変化する関数

を私は、関数のパラメータが多少変化しているパラメータとして関数に関数を渡すことができるようにしたいです。たとえば、これは私がJavaで今すぐにロックされていますものです:

public void doSomethingFancy(Object object, <Some Function Type Here> function) { 
    function.call(object); 
} 

public void doFancyThing(Object obj1, String str1, List list1) { 
    // do stuff 
} 
public void doFancyThing2(Object obj1, RandomObj rObj, Integer int1) { 
    // do stuff 
} 
... 
doSomething("hello", this::doFancyThing); 
doSomething("hello", this::doFancyThing2); 

は基本的に私は、変数の型を持っている入力機能が欲しい:

public void doSomething(Object object, Action1<Object> function) { 
    function.call(object); 
} 

public void doOtherThing(Object obj) { 
    System.out.println(obj); 
} 

doSomething("hello", this::doOtherThing); 

これは私が行うことができるようにしたいものです入力パラメータのActionNはオブジェクト配列を私のdoFancyThingメソッドに渡し、明らかにコンパイルされないので動作しません。

+2

カスタムインターフェイスを作成します。 – shmosel

+0

メソッドシグネチャをオーバーロードしますか?あなたは特定の入力パラメータセットを持っていますか? – drelliot

+0

質問を更新しました –

答えて

0

厳密に1つの抽象メソッドを持つインタフェースはすべて、関数インタフェースであるため、ラムダ関数またはメソッド参照を使用して実装できます。

@FunctionalInterface 
public class MyFancyInterface { 
    void call(Object obj1, String str1, List list1); 
} 
0

方法について、

エグゼキュータ・インターフェース:

public interface Executor<T> { 
    void execute(T source); 
} 

シンプルエグゼキュータ:

public class SimpleExecutor implements Executor<String> { 

    @Override 
    public void execute(String source) { 
     System.out.println(source); 
    } 

} 

空想エグゼキュータ:

public class FancyExecutor implements Executor<Object>{ 

    @Override 
    public void execute(Object source) { 
     System.out.println("doing some fancy stuff");   
    } 

} 

処置:

public class Action { 

    public <T> void doSomething(T source, Executor<T> executor) { 
     executor.execute(source); 
    } 

} 

そして最後に:あなたの定義は、doSomethingFancy("hello", this::doFancyThing);

public static void main(String [] args) { 
    Action action = new Action(); 
    action.doSomething("hey there", new SimpleExecutor()); 
    action.doSomething(new Object(), new FancyExecutor()); 
} 
0

(私はあなたがこの代わりに、第二の例でdoSomething("hello", this::doFancyThing);を望んでいたと仮定)は不可能である、doFancyThing("hello")を呼び出す必要があります:それはです2つの引数がありません! doSomethingFancy("hello", this::doFancyThing2);についても同様で、doFancyThing2("hello")を呼び出します。

そして、あなたはそれについて少し考えるならば、あなたはdoSomethingFancyの定義を変更しても解決しないことを見つける必要があります:(など、nullobjectfunction.hashCode()を返すような些細な事を除く)、それは行うことができますだけでは何もありません。だから、あなたがそれを宣言することさえできないときは、それは良いことです。

二つの実際の可能性:

  1. は、機能の一部として不足している引数を提供します

    public <T> void doSomething(T object, Action1<T> function) { 
        function.call(object); 
    } 
    
    doSomething("hello", x -> doFancyThing(x, "a", Collections.<Integer> emptyList())); 
    doSomething("hello", x -> doFancyThing2(x, some other arguments)); 
    

    これは動作し、それは素晴らしい作品。

  2. 使用すると、すべてのパラメータを供給するために可変引数:

    public void doSomething(Action1<Object[]> function, Object... args) { 
        function.call(object); 
    } 
    
    doSomething(args -> doFancyThing((Object) args(0), (String) args(1), (List) args(2)), "hello", "a", Collections.<Integer> emptyList())); 
    

    あなたは一般的な方法にargs -> doFancyThing((Object) args(0), (String) args(1), (List) args(2))一部を抽出でき、その呼び出しはこれは次のように残され

    doSomething(toVarArgs(this::doFancyThing), "hello", "a", Collections.<Integer> emptyList())); 
    

ようになります。運動。

関連する問題