我有许多映射到服务器请求的方法。请求使用promises(来自Play Framework)在将来的某个时间返回响应。以下是我的一个行动示例:
public static Promise<Result> someAction() {
MyBean data = new MyBean(getData(request().body()));
Promise<MyReq> promise = Promise.promise(() -> new MyReq(data));
return promise.map((MyReq req) -> ok(req.getResponse()));
}
请注意,MyReq
扩展了MyAbstractReq<T>
。
我希望能够从所有操作方法中获取所有常用代码,并将其捆绑到单个通用handleRequest
方法中。但是我很难理解Lambda Notation并且无法修改代码以适合我的目的。
我理解() -> new MyReq(data)
基本上意味着(arg1, arg2, ...) -> { body }
,可以写成(我认为):
MyBean data = new MyBean(getData(request().body()));
// Anonymous Functional Interface
MyFunction f = new MyFunction() {
@Override
public void getReq(){
return new MyReq(data);
}
};
或类似的东西。
但是我想要实现的是这样的事情(不编译,但我希望它足以让我知道我想要实现的目标):
public static Promise<Result> handleRequest(MyAbstractReq<?> req) {
Promise<MyAbstractReq<?>> promise = Promise.promise(() -> req);
return promise.map(() -> ok(req.getResponse()));
}
每个动作都是这样的:
public static Promise<Result> someAction() {
MyBean data = new MyBean(getData(request().body()));
return handleRequest(new MyReq(data));
}
有人可以指出我对Lambda表示法缺少什么,并解释我如何能够实现我想要做的事情。
更新
我得到的错误是
Lambda expression's signature does not match the signature of the functional interface method apply(? super MyAbstractReq<?>)
我猜这是因为语法错误,这只是我第一次尝试重构它。
req.getResponse()
方法并不真正相关,因为它只生成一个Json对象(ObjectNode - Jackson更快的xml),ok()
方法可以使用它来创建Result
更新2
关于使用handleRequest(MyAbstractReq<T> req)
我最初实际上有这个,但错误基本相同。
Lambda expression's signature does not match the signature of the functional interface method apply(? super MyAbstractReq<T>)
更新3
请原谅。错误在return promise.map(() -> ok(req.getResponse()));
行
更新4
我可能应该提到我知道如何通过将handleRequest()
方法更改为:
public static Promise<Result> handleRequest(MyAbstractReq<?> req) {
Promise<MyAbstractReq<?>> promise = Promise.promise(() -> req);
return promise.map((MyAbstractReq<?> notUsed) -> ok(req.getResponse()));
}
但感觉不对,因为第return promise.map((MyAbstractReq<?> notUsed) -> ok(req.getResponse()));
行采用了从未使用的MyAbstractReq<?>
参数。
我对Lambda表达式的符号知之甚少,不知道这是不是达到我想要的最佳方式(我没有提及它,因为我想看看如果没有我引导他们,人们的建议是什么回答)。
答案 0 :(得分:2)
在您的初始代码中
public static Promise<Result> someAction() {
MyBean data = new MyBean(getData(request().body()));
Promise<MyReq> promise = Promise.promise(() -> new MyReq(data));
return promise.map((MyReq req) -> ok(req.getResponse()));
}
一切都按预期工作,map
获取一个函数,指定如何处理参数req
。但是在重构的代码中,您突然尝试从外部作用域访问变量,而不是保留逻辑:
public static Promise<Result> handleRequest(MyAbstractReq<?> req) {
Promise<MyAbstractReq<?>> promise = Promise.promise(() -> req);
// the following function refers to handleRequest’s parameter instead of its argument
return promise.map((MyAbstractReq<?> notUsed) -> ok(req.getResponse()));
}
这适用于这种特殊情况,但确实和你的感觉一样错误。
请坚持原始逻辑:
public static Promise<Result> handleRequest(MyAbstractReq<?> req) {
Promise<MyAbstractReq<?>> promise = Promise.promise(() -> req);
// arg is unrelated to req here though both variables happen to have to same contents
return promise.map(arg -> ok(arg.getResponse()));
}
但它仍然有点奇怪,因为promise是围绕一个已经存在的对象构建的,而不是构造它。也许你想要
public static Promise<Result> handleRequest(Function0<MyAbstractReq<?>> supplier) {
Promise<MyAbstractReq<?>> promise = Promise.promise(supplier);
return promise.map(arg -> ok(arg.getResponse()));
}
所以你可以像
一样调用它handleRequest( ()-> new MyReq(new MyBean(getData(request().body()))) );
然后Promise
将真正涵盖整个操作。
答案 1 :(得分:2)
现在,在您的更新2之后,您已经提出了以下方法:
public static Promise<Result> handleRequest(MyAbstractReq<?> req) {=
Promise<MyAbstractReq<?>> promise = Promise.promise(() -> req);
return promise.map((MyAbstractReq<?> notUsed) -> ok(req.getResponse()));
}
在继续讨论之前,让我解释一下map()
的作用。在给定的Iterable
上,map()
将简单地将每个元素转换为其他元素(可能是从元素中提取的内容)。为此,我们将Function
传递给map()
方法,该方法接受输入并返回输出。
在这种情况下,(MyAbstractReq<?> notUsed) -> ok(req.getResponse())
就是那个功能。您将notUsed
作为参数(这是promise
中的一个元素,并在响应该对象时调用ok()
方法。
但是你看,你没有使用你传递的参数,而是使用另一个对象(你作为handleRequest()
方法的参数传递的那个。这是错误的。你应该使用notUsed.getResponse()
那里。
此外,您不需要在那里提供notUsed
类型。 Java可以推断出类型。因此,将您的方法更改为:
public static Promise<Result> handleRequest(MyAbstractReq<?> req) {=
Promise<MyAbstractReq<?>> promise = Promise.promise(() -> req);
return promise.map(promReq -> ok(promReq.getResponse()));
}