在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
方法,而且显然无法编译。
答案 0 :(得分:0)
任何只有一个抽象方法的接口都是一个功能接口,因此可以使用lambda函数或方法引用来实现。
@FunctionalInterface
public class MyFancyInterface {
void call(Object obj1, String str1, List list1);
}
答案 1 :(得分: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);
}
}
最后:
public static void main(String [] args) {
Action action = new Action();
action.doSomething("hey there", new SimpleExecutor());
action.doSomething(new Object(), new FancyExecutor());
}
答案 2 :(得分:0)
根据您的定义doSomethingFancy("hello", this::doFancyThing);
(我假设您希望在第二个示例中使用此代替doSomething("hello", this::doFancyThing);
)应该调用doFancyThing("hello")
,这是不可能的:它缺少两个参数!同样适用于调用doSomethingFancy("hello", this::doFancyThing2);
的{{1}}。
如果你仔细想一想,你应该发现更改doFancyThing2("hello")
的定义无济于事:它无能为力(除了返回doSomethingFancy
,{{null
之外的琐事1}},object
等)。因此,当语言不能让你宣布它时,这是一件好事。
两种实际可能性:
提供缺少的参数作为函数的一部分:
function.hashCode()
这很有效,效果很好。
使用varargs提供所有参数:
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));
您可以将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))
这是一项练习。