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