Lambda 表示法 - 尝试重构但遇到问题
Lambda notation - Trying to refactor but getting issues
我有许多映射到服务器请求的方法。请求使用 promises(来自 Play Framework)到将来某个时间的 return 响应。这是我的其中一项操作的示例:
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 表示法,无法修改代码以满足我的目的。
我理解 () -> 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 表达式的表示法了解不够,无法判断这是否不是实现我想要的目标的最佳方式(我没有提及它是因为我想看看如果没有我,人们的建议会是什么引导他们找到答案)。
在您的初始代码中
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
将真正涵盖整个操作。
现在在你的更新 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()
方法,该方法接受输入和 returns 输出。
在这种情况下,(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()));
}
我有许多映射到服务器请求的方法。请求使用 promises(来自 Play Framework)到将来某个时间的 return 响应。这是我的其中一项操作的示例:
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 表示法,无法修改代码以满足我的目的。
我理解 () -> 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 表达式的表示法了解不够,无法判断这是否不是实现我想要的目标的最佳方式(我没有提及它是因为我想看看如果没有我,人们的建议会是什么引导他们找到答案)。
在您的初始代码中
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
将真正涵盖整个操作。
现在在你的更新 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()
方法,该方法接受输入和 returns 输出。
在这种情况下,(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()));
}