Я пытаюсь понять цель reifiedключевого слова, по-видимому, оно позволяет нам размышлять о дженериках .
Однако, когда я оставляю это, это работает так же хорошо. Кто-нибудь хочет объяснить, когда это имеет значение ?
Я пытаюсь понять цель reifiedключевого слова, по-видимому, оно позволяет нам размышлять о дженериках .
Однако, когда я оставляю это, это работает так же хорошо. Кто-нибудь хочет объяснить, когда это имеет значение ?
Ответы:
reifiedхорошо дляfun <T> myGenericFun(c: Class<T>)
В теле общей функции, такой как myGenericFun, вы не можете получить доступ к типу, Tпотому что он доступен только во время компиляции, но стирается во время выполнения. Поэтому, если вы хотите использовать универсальный тип в качестве обычного класса в теле функции, вам нужно явно передать класс в качестве параметра, как показано в myGenericFun.
Если вы создаете inlineфункцию с помощью reified, T то к ее типу Tможно обращаться даже во время выполнения, и, таким образом, вам не нужно Class<T>дополнительно передавать . Вы можете работать с Tкак если бы это был обычный класс, например , вы можете захотеть , чтобы проверить , является ли переменная является экземпляром T , который вы можете легко сделать , то: myVar is T.
Такая inlineфункция с reifiedтипом Tвыглядит следующим образом:
inline fun <reified T> myGenericFun()
reifiedработаетВы можете использовать только reifiedв сочетании с inlineфункцией . Такая функция заставляет компилятор копировать байт-код функции в каждое место, где используется функция (функция «встроена»). Когда вы вызываете встроенную функцию с типом reified, компилятор знает фактический тип, используемый в качестве аргумента типа, и модифицирует сгенерированный байт-код для непосредственного использования соответствующего класса. Поэтому вызовы like myVar is Tстановятся myVar is String(если аргумент типа был String) в байт-коде и во время выполнения.
Давайте посмотрим на пример, который показывает, насколько полезным reifiedможет быть. Мы хотим создать функцию расширения для Stringвызываемого, toKotlinObjectкоторая пытается преобразовать строку JSON в простой объект Kotlin с типом, указанным универсальным типом функции T. Мы можем использовать com.fasterxml.jackson.module.kotlinдля этого, и первый подход заключается в следующем:
а) первый подход без ограниченного типа
fun <T> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
//does not compile!
return mapper.readValue(this, T::class.java)
}
readValueМетод принимает тип , который он , как предполагается разобрать JsonObjectк. Если мы пытаемся получить Classпараметр типа T, компилятор жалуется: «Невозможно использовать« T »в качестве параметра типа reified. Вместо этого используйте класс».
б) Обходной путь с явным Classпараметром
fun <T: Any> String.toKotlinObject(c: KClass<T>): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, c.java)
}
Чтобы обойти эту проблему, то Classиз Tможет быть сделан параметр метода, который затем используется в качестве аргумента readValue. Это работает и является общим шаблоном в общем коде Java. Это можно назвать следующим образом:
data class MyJsonType(val name: String)
val json = """{"name":"example"}"""
json.toKotlinObject(MyJsonType::class)
в) путь Котлина: reified
Использование inlineфункции с reifiedпараметром типа Tпозволяет реализовать функцию по-разному:
inline fun <reified T: Any> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, T::class.java)
}
Там нет необходимости брать Classиз Tдополнительно, Tможет быть использован , как если бы это был обычный класс. Для клиента код выглядит так:
json.toKotlinObject<MyJsonType>()
Встроенная функция с reifiedтипом не вызывается из кода Java .
ПРОСТО
* reified - это разрешение на использование во время компиляции (для доступа к T внутри функции de)
например:
inline fun <reified T:Any> String.convertToObject(): T{
val gson = Gson()
return gson.fromJson(this,T::class.java)
}
используя как:
val jsonStringResponse = "{"name":"bruno" , "age":"14" , "world":"mars"}"
val userObject = jsonStringResponse.convertToObject<User>()
println(user.name)