为什么不能从构造函数中推断出 Kotlin 超类型参数?
Why can't Kotlin super type parameters be inferred from constructor?
在 Kotlin 中,如果我们有一个 class w/constructor:
open class Wrapper<T>(val value: T)
我们可以在不指定类型参数的情况下调用构造函数:
val wrapped = Wrapper("value")
指定类型参数(例如 Wrapper<String>("value")
)是多余的,IntelliJ 会告诉你的。
但是,如果构造函数调用是一个扩展子句,则类型参数是必需的。例如
class StringWrapper : Wrapper<String>("value") // compiles
class StringWrapper : Wrapper("value") // does not compile
为什么在这种看似非常相似的情况下无法推断出类型参数?
在这种情况下,当然可以 推断出类型参数,但是编译器中还没有代码可以做到这一点。 JetBrains 团队成员 Stanislav Erokhin 在 2017 年对此发表评论 here。
[...] for now compiler force users declare type arguments for parent
class explicitly.
让我们来试验一下。编译器源代码中有问题的检查是 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
让它发挥作用需要更大的改变...
所以,简而言之,理论上是可以的,但还没有实现。
在 Kotlin 中,如果我们有一个 class w/constructor:
open class Wrapper<T>(val value: T)
我们可以在不指定类型参数的情况下调用构造函数:
val wrapped = Wrapper("value")
指定类型参数(例如 Wrapper<String>("value")
)是多余的,IntelliJ 会告诉你的。
但是,如果构造函数调用是一个扩展子句,则类型参数是必需的。例如
class StringWrapper : Wrapper<String>("value") // compiles
class StringWrapper : Wrapper("value") // does not compile
为什么在这种看似非常相似的情况下无法推断出类型参数?
在这种情况下,当然可以 推断出类型参数,但是编译器中还没有代码可以做到这一点。 JetBrains 团队成员 Stanislav Erokhin 在 2017 年对此发表评论 here。
[...] for now compiler force users declare type arguments for parent class explicitly.
让我们来试验一下。编译器源代码中有问题的检查是 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
让它发挥作用需要更大的改变...
所以,简而言之,理论上是可以的,但还没有实现。