reifiedAnahtar kelimenin amacını anlamaya çalışıyorum , görünüşe göre jenerikler üzerinde düşünmemize izin veriyor .
Ancak, onu dışarıda bıraktığımda da gayet iyi çalışıyor. Bunun gerçek bir fark yarattığını açıklamak isteyen var mı?
reifiedAnahtar kelimenin amacını anlamaya çalışıyorum , görünüşe göre jenerikler üzerinde düşünmemize izin veriyor .
Ancak, onu dışarıda bıraktığımda da gayet iyi çalışıyor. Bunun gerçek bir fark yarattığını açıklamak isteyen var mı?
Yanıtlar:
reifiediyifun <T> myGenericFun(c: Class<T>)
Gibi genel bir işlevin gövdesinde, türe myGenericFunerişemezsiniz Tçünkü yalnızca derleme zamanında kullanılabilir ancak çalışma zamanında silinir . Bu nedenle, genel türü işlev gövdesinde normal bir sınıf olarak kullanmak istiyorsanız, sınıfı içinde gösterildiği gibi bir parametre olarak açıkça iletmeniz gerekir myGenericFun.
Yine de somutlaştırılmış bir inlineişlev oluşturursanız , türüne çalışma zamanında bile erişilebilir ve bu nedenle ek olarak geçmeniz gerekmez . Sen çalışabilir bir değişken bir olup olmadığını kontrol etmek isteyebilirsiniz örneğin, normal bir sınıf sanki örneği kolayca ardından yapabilirsiniz: . TTClass<T>T TmyVar is T
Type inlineile böyle bir işlev aşağıdaki gibi görünür:reifiedT
inline fun <reified T> myGenericFun()
reifiedçalışırYalnızca reifiedbir inlineişlevle birlikte kullanabilirsiniz . Böyle bir işlev, derleyicinin işlevin bayt kodunu işlevin kullanıldığı her yere kopyalamasını sağlar (işlev "satır içi" halindedir). Gerçekleştirilmiş türle bir satır içi işlevi çağırdığınızda, derleyici , tür bağımsız değişkeni olarak kullanılan gerçek türü bilir ve ilgili sınıfı doğrudan kullanmak için üretilen bayt kodunu değiştirir. Gibi nedenle çağıran myVar is Thaline myVar is String(tip argüman olsaydı String) byte ve zamanında.
Ne kadar yararlı reifiedolabileceğini gösteren bir örneğe bakalım . Bir JSON dizesini, işlevin genel türü tarafından belirtilen bir türe sahip düz bir Kotlin nesnesine dönüştürmeye çalışan Stringçağrılan için bir uzantı işlevi oluşturmak istiyoruz . Bunun için kullanabiliriz ve ilk yaklaşım şudur:toKotlinObjectTcom.fasterxml.jackson.module.kotlin
a) Reified türü olmayan ilk yaklaşım
fun <T> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
//does not compile!
return mapper.readValue(this, T::class.java)
}
readValueYöntem ayrıştırmak gerekiyor o bir türü alır JsonObjectbelirleyin. ClassType parametresini almaya çalışırsak T, derleyici şikayet eder: "Reified type parametresi olarak 'T' kullanılamaz. Bunun yerine bir sınıf kullanın."
b) Açık Classparametre ile geçici çözüm
fun <T: Any> String.toKotlinObject(c: KClass<T>): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, c.java)
}
Geçici bir çözüm olarak, Classof T, daha sonra bir argüman olarak kullanılan bir yöntem parametresi yapılabilir readValue. Bu çalışır ve jenerik Java kodunda yaygın bir kalıptır. Aşağıdaki gibi çağrılabilir:
data class MyJsonType(val name: String)
val json = """{"name":"example"}"""
json.toKotlinObject(MyJsonType::class)
c) Kotlin yolu: reified
Type parametresine inlinesahip bir işlev kullanmak , işlevi farklı şekilde uygulamayı mümkün kılar:reifiedT
inline fun <reified T: Any> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, T::class.java)
}
Almaya gerek yok Classve Tayrıca, Tsıradan bir sınıf olsaydı olarak kullanılabilir. Müşteri için kod şuna benzer:
json.toKotlinObject<MyJsonType>()
İle bir satır içine fonksiyon reifiedtürü olan Java dan çağrılabilir değildir kodu.
BASİT
* derleme zamanında kullanım izni vermektir (işlev içinde T'ye erişmek için)
Örneğin:
inline fun <reified T:Any> String.convertToObject(): T{
val gson = Gson()
return gson.fromJson(this,T::class.java)
}
gibi kullanarak:
val jsonStringResponse = "{"name":"bruno" , "age":"14" , "world":"mars"}"
val userObject = jsonStringResponse.convertToObject<User>()
println(user.name)