我正在开发一个http4k网络应用程序。Http4k为http处理程序和过滤器(也就是拦截器)提供了一个很好的功能方案。
typealias HttpHandler = (Request) -> Response
interface Filter : (HttpHandler) -> HttpHandler {...}我想编写一个简单的过滤器,所以我创建了一个函数,返回一个
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为什么科特林不能推断这些类型实际上是相同的?
发布于 2020-04-02 15:12:38
过滤器是扩展(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实际上是一个(HttpHandler) -> HttpHandler,不能推断它是一个过滤器,就像任意的动物可以被投射到一个小猫身上一样。重要的是,我们没有碰巧添加任何函数到Kitten或覆盖任何东西。这仅仅是声明,意味着它是一个独特的子类型,编译器永远也不会这样认为。
发布于 2020-04-02 10:16:11
您可以使用Filter() ~构造函数~重载操作符函数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()
}
}https://stackoverflow.com/questions/60988186
复制相似问题