2017-08-16 68 views
0

在Java和Scala,我將如何做到以下幾點:創建一個參數是一個變函數

我希望能夠給一個函數傳遞到一個函數作爲參數,其中函數參數有所不同。例如,這就是我鎖定在現在的Java:

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

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

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

這就是我希望能夠做到:

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); 

基本上我想要的輸入功能具有可變型的輸入參數。 ActionN將無法工作,因爲這將傳遞一個對象數組到我的doFancyThing方法,並且顯然不能編譯。

+2

製作自定義界面。 – shmosel

+0

過載加載方法簽名?你有一組特定的輸入參數嗎? – drelliot

+0

更新了問題 –

回答

0

只有一個抽象方法的任何接口都是一個功能接口,因此可以使用lambda函數或方法引用來實現。

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

怎麼樣,

的Executor接口:

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); 
    } 

} 

最後:

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

有了您的定義,doSomethingFancy("hello", this::doFancyThing);(我假設你想要這個,而不是在第二個例子doSomething("hello", this::doFancyThing);)應該叫doFancyThing("hello"),這是不可能的:它是缺少兩個參數! 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())); 
    

這將留作練習。

相關問題