为什么不能从构造函数中推断出Kotlin超类型参数?

时间:2019-09-16 12:57:59

标签: generics kotlin type-inference

在Kotlin中,如果我们有一个带有构造函数的类:

open class Wrapper<T>(val value: T)

我们可以在不指定type参数的情况下调用构造函数:

val wrapped = Wrapper("value")

指定类型参数(例如Wrapper<String>("value"))是多余的,IntelliJ会告诉您。

但是,如果构造函数调用是extends子句,则类型参数是必需的。例如

class StringWrapper : Wrapper<String>("value") // compiles
class StringWrapper : Wrapper("value") // does not compile

为什么在这种看似非常相似的情况下无法推断出类型参数?

2 个答案:

答案 0 :(得分:1)

在这种情况下当然可以推断出类型参数 ,但是编译器中尚无用于执行此操作的代码。 JetBrains团队成员Stanislav Erokhin在2017年对此here进行了评论。

  

[...]现在,编译器强制用户为父声明类型参数   明确地上课。

让我们做一点实验。编译器源代码中有问题的检查是here

if (currentArguments.size != currentParameters.size) {
    c.trace.report(
        WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(
            qualifierPart.typeArguments ?: qualifierPart.expression,
            currentParameters.size, classifierDescriptorChain[index]
        )
    )
    return null
}

如果我们删除该支票怎么办?原来我们摆脱了

error: one type argument expected for class Wrapper<T>

但是我们走得更远。相反,我们得到

error: type arguments should be specified for an outer class 'Wrapper'. Use full class name to specify them

要使其正常工作,将需要进行更大的更改...

因此,简而言之,从理论上讲这是可能的,但尚未实现。

答案 1 :(得分:0)

Kotlin中的类型推断仅限于变量和函数,并且仅在某些情况下可用。例如:

val s = "42"

s将具有String类型,在这种情况下:

fun f() = { "42" }

类型为f() : String

但是kotlin不能推断Type变量的类型,除非您告诉它。