0

我正在开发一个http4k网络应用程序。Http4k为 http 处理程序和过滤器(又名拦截器)提供了一个很好的功能方案。

typealias HttpHandler = (Request) -> Response

interface Filter : (HttpHandler) -> HttpHandler {...}

我想写一个简单的过滤器,所以我创建了一个函数,它返回一个Filter

fun throwNotFoundResponses(): Filter {
    return { next: HttpHandler ->
        { request: Request ->
            val response = next(request)
            if (response.status == Status.NOT_FOUND) {
                throw NotFoundException()
            }
            response
        }
    }
}

// example usage
Filter.NoOp
        .then(throwNotFoundResponses())
        .then(routes(...))

然而 Kotlin 抱怨(编辑行号以匹配上面的示例。)

NotFoundThrower.kt: (2, 12): Type mismatch: inferred type is (HttpHandler /* = (Request) -> Response */) -> (Request) -> Response but Filter was expected

为什么 Kotlin 不能推断类型实际上是相同的?

4

2 回答 2

1

您可以使用Filter()~constructor~ 重载运算符函数invoke并为其提供过滤器功能:

fun throwNotFoundResponses(): Filter {
    return Filter { next: HttpHandler ->
        { request: Request ->
            val response = next(request)
            if (response.status == Status.NOT_FOUND) {
                throw NotFoundException()
            }
            response
        }
    }
}

或更简洁:

fun throwNotFoundResponses(): Filter = Filter { next: HttpHandler ->
    { request: Request ->
        next(request).takeIf { it.status != Status.NOT_FOUND } 
            ?: throw NotFoundException()
    }
}
于 2020-04-02T10:16:11.703 回答
1

Filter 是一个扩展接口(HttpHandler) -> HttpHandler,所以它是它的子类,而不是超类。

也许更容易看出您是否没有功能语法。

open class Animal
class Kitten: Animal()

fun doSomething(): Kitten {
    // You cannot return an explicit Animal here, even though the Kitten implementation
    // has not defined any unique members or overridden anything. 
}

您的 lambda 实际上是 a(HttpHandler) -> HttpHandler并且不能被推断为过滤器,就像可以将任意 Animal 转换为 Kitten 一样。我们没有碰巧向 Kitten 添加任何功能或覆盖任何东西,这并不重要。它只是声明意味着它是一个独特的子类型,编译器永远不会假设。

于 2020-04-02T15:12:38.090 回答