reified
Anahtar 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ı?
reified
Anahtar 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:
reified
iyifun <T> myGenericFun(c: Class<T>)
Gibi genel bir işlevin gövdesinde, türe myGenericFun
eriş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 inline
iş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: . T
T
Class<T>
T
T
myVar is T
Type inline
ile böyle bir işlev aşağıdaki gibi görünür:reified
T
inline fun <reified T> myGenericFun()
reified
çalışırYalnızca reified
bir inline
iş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 T
haline myVar is String
(tip argüman olsaydı String
) byte ve zamanında.
Ne kadar yararlı reified
olabileceğ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:toKotlinObject
T
com.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)
}
readValue
Yöntem ayrıştırmak gerekiyor o bir türü alır JsonObject
belirleyin. Class
Type 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 Class
parametre 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, Class
of 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 inline
sahip bir işlev kullanmak , işlevi farklı şekilde uygulamayı mümkün kılar:reified
T
inline fun <reified T: Any> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, T::class.java)
}
Almaya gerek yok Class
ve T
ayrıca, T
sı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 reified
tü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)