Próbuję zrozumieć cel reifiedsłowa kluczowego, najwyraźniej pozwala nam to na refleksję na temat leków generycznych .
Jednak kiedy to pominę, działa równie dobrze. Czy ktoś chciałby wyjaśnić, kiedy to rzeczywiście robi różnicę ?
Próbuję zrozumieć cel reifiedsłowa kluczowego, najwyraźniej pozwala nam to na refleksję na temat leków generycznych .
Jednak kiedy to pominę, działa równie dobrze. Czy ktoś chciałby wyjaśnić, kiedy to rzeczywiście robi różnicę ?
Odpowiedzi:
reifieddobre dlafun <T> myGenericFun(c: Class<T>)
W treści funkcji ogólnej, takiej jak myGenericFun, nie można uzyskać dostępu do typu, Tponieważ jest on dostępny tylko w czasie kompilacji, ale jest usuwany w czasie wykonywania. Dlatego jeśli chcesz użyć typu ogólnego jako normalnej klasy w treści funkcji, musisz jawnie przekazać klasę jako parametr, jak pokazano w myGenericFun.
Jeśli utworzysz inlinefunkcję z reified T , typ Tmożna uzyskać nawet w czasie wykonywania, a zatem nie musisz Class<T>dodatkowo przekazywać . Można pracować z Ttak jakby to było normalne klasy, na przykład może chcesz sprawdzić, czy zmienna jest instancją T , które można łatwo zrobić wtedy: myVar is T.
Taka inlinefunkcja z reifiedtypem Twygląda następująco:
inline fun <reified T> myGenericFun()
reifieddziałaMożesz używać tylko reifiedw połączeniu z inlinefunkcją . Taka funkcja powoduje, że kompilator kopiuje kod bajtowy funkcji w każde miejsce, w którym funkcja jest używana (funkcja jest „wstawiana”). Kiedy wywołujesz funkcję wbudowaną z typem reified, kompilator zna rzeczywisty typ używany jako argument typu i modyfikuje wygenerowany kod bajtowy, aby bezpośrednio używał odpowiedniej klasy. Dlatego wywołania takie jak myVar is Tget myVar is String(jeśli argument typu był String) w kodzie bajtowym iw czasie wykonywania.
Spójrzmy na przykład, który pokazuje, jak pomocne reifiedmoże być. Chcemy utworzyć funkcję rozszerzającą dla Stringwywoływanej, toKotlinObjectktóra próbuje przekonwertować ciąg JSON na zwykły obiekt Kotlin o typie określonym przez typ ogólny funkcji T. Możemy com.fasterxml.jackson.module.kotlindo tego użyć, a pierwsze podejście jest następujące:
a) Pierwsze podejście bez typu zreifikowanego
fun <T> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
//does not compile!
return mapper.readValue(this, T::class.java)
}
readValueMetoda zajmuje typ, który to ma do analizowania JsonObjectdo. Jeśli spróbujemy pobrać Classparametr typu T, kompilator narzeka: „Nie można użyć 'T' jako parametru typu reified. Zamiast tego użyj klasy.”
b) Obejście z jawnym Classparametrem
fun <T: Any> String.toKotlinObject(c: KClass<T>): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, c.java)
}
Aby obejść ten problem, Classof Tmożna ustawić jako parametr metody, który następnie zostanie użyty jako argument funkcji readValue. To działa i jest częstym wzorcem w ogólnym kodzie Java. Można to nazwać w następujący sposób:
data class MyJsonType(val name: String)
val json = """{"name":"example"}"""
json.toKotlinObject(MyJsonType::class)
c) Droga Kotlina: reified
Użycie inlinefunkcji z reifiedparametrem typu Tumożliwia inną implementację funkcji:
inline fun <reified T: Any> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, T::class.java)
}
Nie ma potrzeby brać dodatkowego Classudziału T, Tmożna z niej korzystać tak, jakby to była zwykła klasa. Dla klienta kod wygląda następująco:
json.toKotlinObject<MyJsonType>()
Funkcja wstawiana z reifiedtypem nie jest wywoływana z kodu Java .
PROSTY
* reified to udzielenie pozwolenia na użycie w czasie kompilacji (aby uzyskać dostęp do funkcji T inside de)
na przykład:
inline fun <reified T:Any> String.convertToObject(): T{
val gson = Gson()
return gson.fromJson(this,T::class.java)
}
używając takich jak:
val jsonStringResponse = "{"name":"bruno" , "age":"14" , "world":"mars"}"
val userObject = jsonStringResponse.convertToObject<User>()
println(user.name)