Saya mencoba memahami tujuan reified
kata kunci, tampaknya itu memungkinkan kami untuk melakukan refleksi pada obat generik .
Namun, ketika saya tinggalkan itu berfungsi dengan baik. Adakah yang mau menjelaskan kapan ini membuat perbedaan nyata ?
Saya mencoba memahami tujuan reified
kata kunci, tampaknya itu memungkinkan kami untuk melakukan refleksi pada obat generik .
Namun, ketika saya tinggalkan itu berfungsi dengan baik. Adakah yang mau menjelaskan kapan ini membuat perbedaan nyata ?
Jawaban:
reified
baik untukfun <T> myGenericFun(c: Class<T>)
Dalam tubuh fungsi generik seperti myGenericFun
, Anda tidak dapat mengakses tipe T
karena hanya tersedia pada waktu kompilasi tetapi terhapus saat runtime. Oleh karena itu, jika Anda ingin menggunakan tipe generik sebagai kelas normal di fungsi tubuh Anda harus secara eksplisit lulus kelas sebagai parameter seperti yang ditunjukkan pada myGenericFun
.
Jika Anda membuat inline
fungsi dengan reified T
, tipe T
dapat diakses bahkan saat runtime dan dengan demikian Anda tidak perlu meneruskannya Class<T>
. Anda dapat bekerja dengan T
seolah-olah itu adalah kelas normal, misalnya Anda mungkin ingin memeriksa apakah suatu variabel adalah contoh dari T
yang Anda dapat dengan mudah melakukan itu: myVar is T
.
Seperti inline
fungsi dengan reified
tipe T
penampilan sebagai berikut:
inline fun <reified T> myGenericFun()
reified
kerjanyaAnda hanya dapat menggunakan reified
dalam kombinasi dengan suatu inline
fungsi . Fungsi seperti itu membuat compiler menyalin bytecode fungsi ke setiap tempat di mana fungsi tersebut digunakan (fungsi tersebut sedang "digarisbawahi"). Ketika Anda memanggil fungsi inline dengan tipe reified, kompiler mengetahui tipe aktual yang digunakan sebagai argumen tipe dan memodifikasi bytecode yang dihasilkan untuk menggunakan kelas terkait secara langsung. Oleh karena itu panggilan seperti myVar is T
menjadi myVar is String
(jika argumen tipe String
) di bytecode dan saat runtime.
Mari kita lihat contoh yang menunjukkan betapa bermanfaatnya reified
hal itu. Kami ingin membuat fungsi ekstensi untuk String
dipanggil toKotlinObject
yang mencoba untuk mengkonversi string JSON ke objek Kotlin biasa dengan tipe yang ditentukan oleh tipe generik fungsi T
. Kita dapat menggunakan com.fasterxml.jackson.module.kotlin
ini dan pendekatan pertama adalah sebagai berikut:
a) Pendekatan pertama tanpa tipe reified
fun <T> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
//does not compile!
return mapper.readValue(this, T::class.java)
}
The readValue
Metode mengambil jenis yang seharusnya untuk mengurai JsonObject
ke. Jika kita mencoba untuk mendapatkan Class
parameter tipe T
, kompiler mengeluh: "Tidak dapat menggunakan 'T' sebagai parameter tipe reified. Gunakan kelas sebagai gantinya."
b) Penanganan masalah dengan Class
parameter eksplisit
fun <T: Any> String.toKotlinObject(c: KClass<T>): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, c.java)
}
Sebagai solusinya, Class
dari T
dapat dibuat parameter metode, yang kemudian digunakan sebagai argumen untuk readValue
. Ini berfungsi dan merupakan pola umum dalam kode Java generik. Itu bisa disebut sebagai berikut:
data class MyJsonType(val name: String)
val json = """{"name":"example"}"""
json.toKotlinObject(MyJsonType::class)
c) Cara Kotlin: reified
Menggunakan inline
fungsi dengan reified
parameter tipe T
memungkinkan untuk mengimplementasikan fungsi secara berbeda:
inline fun <reified T: Any> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, T::class.java)
}
Tidak perlu untuk mengambil Class
dari T
tambahan, T
dapat digunakan sebagai olah itu adalah kelas biasa. Untuk klien, kode ini terlihat seperti ini:
json.toKotlinObject<MyJsonType>()
Fungsi sebaris dengan reified
tipe tidak dapat dipanggil dari kode Java .
SEDERHANA
* Reified adalah untuk memberikan izin untuk digunakan pada waktu kompilasi (untuk mengakses fungsi T inside de)
misalnya:
inline fun <reified T:Any> String.convertToObject(): T{
val gson = Gson()
return gson.fromJson(this,T::class.java)
}
menggunakan like:
val jsonStringResponse = "{"name":"bruno" , "age":"14" , "world":"mars"}"
val userObject = jsonStringResponse.convertToObject<User>()
println(user.name)