为什么 Kotlin 类型推断不适用于函数式接口?
Why Kotlin type inference does not work for functional interface?
我正在为 http 处理程序和过滤器(又名拦截器)开发 http4k web app. Http4k has a nice functional scheme。
typealias HttpHandler = (Request) -> Response
interface Filter : (HttpHandler) -> HttpHandler {...}
我想写一个简单的过滤器,所以我创建了一个函数 returns a 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 不能推断类型实际上是相同的?
你可以使用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()
}
}
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 实际上是一个 (HttpHandler) -> HttpHandler
并且不能被推断为一个过滤器,就像一个任意的动物可以被投射到一只小猫一样。我们没有碰巧向 Kitten 添加任何功能或覆盖任何东西都没有关系。这仅仅是声明意味着它是一个独特的子类型,编译器永远不会假设。
我正在为 http 处理程序和过滤器(又名拦截器)开发 http4k web app. Http4k has a nice functional scheme。
typealias HttpHandler = (Request) -> Response
interface Filter : (HttpHandler) -> HttpHandler {...}
我想写一个简单的过滤器,所以我创建了一个函数 returns a 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 不能推断类型实际上是相同的?
你可以使用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()
}
}
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 实际上是一个 (HttpHandler) -> HttpHandler
并且不能被推断为一个过滤器,就像一个任意的动物可以被投射到一只小猫一样。我们没有碰巧向 Kitten 添加任何功能或覆盖任何东西都没有关系。这仅仅是声明意味着它是一个独特的子类型,编译器永远不会假设。