为什么 Kotlin 中有 reified 关键字,将函数标记为内联还不够吗?

Sil*_*ion 8 kotlin kotlin-reified-type-parameters

在 Kotlin 中,鉴于“reified”关键字只能用于内联函数的泛型类型参数,为什么还要有 reified 关键字呢?为什么 Kotlin 编译器(至少在未来)不能自动将内联函数的所有泛型类型参数视为具体化?

我发现人们在看到这个“具体化”一词时感到恐慌,并要求我不要使代码变得复杂。因此就有了这个问题。

Мих*_*аль 4

具体化类型参数也需要传入其中的类型参数进行具体化。有时这是一个不可能的要求(例如,类参数无法具体化),因此默认情况下具体化内联函数的所有参数将使得在现在只能调用所有内联函数的情况下无法调用所有内联函数不可能用具体化类型参数来调用:

\n
inline fun<T> genericFun(x: T)  {}\ninline fun<reified T> reifiedGenericFun(x: T)  {}\n\nclass SimpleGenericClass<T>() {\n    fun f(x: T) {\n        genericFun<T>(x)        //compiles fine\n        reifiedGenericFun<T>(x) //compilation error\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

更新。为什么不根据上下文自动推断“可重构性”?

\n
    \n
  1. 方法1(由@Tenfour04建议):分析内联函数的代码,如果它有调用,则将其类型参数视为具体化T::class(我还添加了is T调用)。
  2. \n
  3. 方法2(由@SillyQuestion建议):默认情况下将内联函数的所有类型参数视为具体化;如果它导致使用站点上的编译错误,则回退到非具体化类型。
  4. \n
\n

这是两者的反例"a" as? T:具有此主体的函数将具有不同的语义,具体取决于其类型参数是否被声明(或者假设推断)为具体化:

\n
inline fun<reified T> castToReifiedGenericType() = "a" as? T\ninline fun<T> castToSimpleGenericType() = "a" as? T\n\nfun main() {\n    println(castToReifiedGenericType<Int>()) //null\n    println(castToSimpleGenericType<Int>())  //a\n}\n\n/*P.S. unsafe cast ("a" as T) also have different semantics for reified and non-reified T, \ncausing `ClassCastException` in the first case and still returning "a" in the latter.*/\n
Run Code Online (Sandbox Code Playgroud)\n

因此,使用第一种方法,如果我们在内联函数内的某处添加对T::class/ 的无意义调用,语义就会改变。is T第二个 - 如果我们从新站点调用此函数(其中T不能reified,而它之前是“可具体化”的),则语义会改变,或者,\xd1\x81相反,从该站点删除调用(允许它是reified)。

\n

调试来自这些操作的问题(乍一看与观察语义变化无关)比添加/读取显式reified关键字更复杂且更容易引起恐慌。

\n