重载函数扩展时无法解析类型推断

时间:2018-01-29 11:32:54

标签: kotlin kotlin-extension

给定以下方法扩展(JsonResult只是一个带有一些附加字段的包装器):

fun <T, R> T.toJson(transform: (T) -> R) = JsonResult(transform(this))

fun <T, R> List<T>.toJson(transform: (T) -> R) = JsonResult(this.map(transform))

fun <T, R> Page<T>.toJson(transform: (T) -> R) = JsonResult(this.content.map(transform)

当我尝试从列表或不是列表的对象调用上述任何方法时,我得到编译器错误,其中包含我期望的消息Cannot choose among the following candidates without completing type inference

import org.springframework.data.domain.Page

val person = Person()
person.toJson { } // compiler error

val people = List<Person>()
people.toJson { } // compiler error

val pageablePeople = Page<Person>
pageablePeople.toJson { } 

我想知道是否有其他(惯用?)方式来声明这些函数而不更改其名称。

1 个答案:

答案 0 :(得分:0)

您遇到重载解析错误的原因是因为List<T>类型的接收方与fun <T, R> T.toJsonfun <T, R> List<T>.toJson都匹配。

带有未绑定接收器的扩展功能可能会出现问题,因为它们会出现在每个自动完成建议中,因为它们始终是重载解析的候选者。

我建议将未绑定版本设为顶级版本或将其置于object

示例:

fun <T, R> toJson(t: T, transform: (T) -> R) = JsonResult(transform(t))

fun <T, R> List<T>.toJson(transform: (T) -> R) = JsonResult(map(transform))

fun <T, R> Page<T>.toJson(transform: (T) -> R) = JsonResult(content.map(transform))

fun main(args: Array<String>) {
    val person = Person()
    toJson(person) {}

    val people = listOf<Person>()
    people.toJson { }

    val pageablePeople = Page<Person>()
    pageablePeople.toJson { }
}

此外,对于您可以控制的类,您可以使toJson实例函数在重载决策中始终赢得扩展函数。

class Page<T>(val content: List<T>) {
    fun <R> toJson(transform: (T) -> R) = JsonResult(content.map(transform))
}