reified
キーワードの目的を理解しようとしています。明らかに ジェネリックのリフレクションが可能になっています 。
しかし、私がそれを省くとき、それは同じようにうまく働きます。これが実際に差異になるときを説明したい人はいますか?
reified
name__の利点fun <T> myGenericFun(c: Class<T>)
myGenericFun
name__のような汎用関数の本体では、T
name__型にアクセスできません。これは、はコンパイル時にのみ使用可能ですが、実行時には erased _したがって、汎用タイプを関数本体の通常のクラスとして使用する場合は、myGenericFun
name__に示すように、クラスをパラメーターとして明示的に渡す必要があります。
ただし、reifiedinline
name__を使用してT
name__関数を作成すると、実行時にもT
name__の型にアクセスできるため、Class<T>
を追加で渡す必要はありません。 T
name__を通常のクラスであるかのように操作できます。変数がインスタンスのT
name__であるかどうかを確認することをお勧めします。これはmyVar is T
です。
そのようなinline
name__型reified
name__を持つT
name__関数は、次のようになります。
inline fun <reified T> myGenericFun()
reified
name__の仕組みreified
name__は、 inline
name__関数 と組み合わせてのみ使用できます。このような関数は、コンパイラを関数のバイトコードを、関数が使用されているすべての場所にコピーします(関数は「インライン化」されます)。具体化された型でインライン関数を呼び出すと、コンパイラは型引数として使用される実際の型は、対応するクラスを直接使用するように生成されたバイトコードを変更するため、myVar is T
のような呼び出しは、バイトコードおよび実行時にmyVar is String
になります(型引数がString
name__の場合)。
reified
name__がどれほど役立つかを示す例を見てみましょう。 String
name__と呼ばれるtoKotlinObject
name__の拡張関数を作成して、関数のジェネリック型T
name__で指定された型を持つJSON文字列をプレーンなKotlinオブジェクトに変換しようとします。これには com.fasterxml.jackson.module.kotlin
を使用できます。最初のアプローチは次のとおりです。
a)具体化されていないタイプの最初のアプローチ
fun <T> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
//does not compile!
return mapper.readValue(this, T::class.Java)
}
readValue
name__メソッドは、JsonObject
name__を解析することになっている型を取ります。型パラメーターClass
name__のT
name__を取得しようとすると、コンパイラーは次のように文句を言います。「「T」を具体化された型パラメーターとして使用できません。代わりにクラスを使用してください。」
b)明示的なClass
name__パラメーターの回避策
fun <T: Any> String.toKotlinObject(c: KClass<T>): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, c.Java)
}
回避策として、Class
name__のT
name__をメソッドパラメーターにして、readValue
name__の引数として使用できます。これは機能し、一般的なJavaコードの一般的なパターンです。次のように呼び出すことができます。
data class MyJsonType(val name: String)
val json = """{"name":"example"}"""
json.toKotlinObject(MyJsonType::class)
c)Kotlinの方法:reified
name__
inline
name__型パラメーターreified
name__でT
name__関数を使用すると、関数を異なる方法で実装できます。
inline fun <reified T: Any> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, T::class.Java)
}
Class
name__のT
name__を追加で取得する必要はありません。T
name__は、通常のクラスであるかのように使用できます。クライアントの場合、コードは次のようになります。
json.toKotlinObject<MyJsonType>()
reified
name__型のインライン関数はJavaコードから呼び出しできません。