首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么Kotlin类型推断不适用于功能接口?

为什么Kotlin类型推断不适用于功能接口?
EN

Stack Overflow用户
提问于 2020-04-02 09:21:44
回答 2查看 174关注 0票数 0

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

代码语言:javascript
复制
typealias HttpHandler = (Request) -> Response

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

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

代码语言:javascript
复制
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抱怨(为匹配上面的示例而编辑的行号)。

代码语言:javascript
复制
NotFoundThrower.kt: (2, 12): Type mismatch: inferred type is (HttpHandler /* = (Request) -> Response */) -> (Request) -> Response but Filter was expected

为什么科特林不能推断这些类型实际上是相同的?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-04-02 15:12:38

过滤器是扩展(HttpHandler) -> HttpHandler的接口,所以它是它的子类,而不是超类。

如果没有函数式语法,可能会更容易看出。

代码语言:javascript
复制
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或覆盖任何东西。这仅仅是声明,意味着它是一个独特的子类型,编译器永远也不会这样认为。

票数 1
EN

Stack Overflow用户

发布于 2020-04-02 10:16:11

您可以使用Filter() ~构造函数~重载操作符函数invoke,并向其提供筛选函数:

代码语言:javascript
复制
fun throwNotFoundResponses(): Filter {
    return Filter { next: HttpHandler ->
        { request: Request ->
            val response = next(request)
            if (response.status == Status.NOT_FOUND) {
                throw NotFoundException()
            }
            response
        }
    }
}

或者更简洁:

代码语言:javascript
复制
fun throwNotFoundResponses(): Filter = Filter { next: HttpHandler ->
    { request: Request ->
        next(request).takeIf { it.status != Status.NOT_FOUND } 
            ?: throw NotFoundException()
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60988186

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档