Intereting Posts
Как обновить классы данных, реализующие общий интерфейс Матч скобки kotlin способ Объединение обязательных и произвольных необязательных аргументов конструктора с Groovy Нежелательные выборы в RecyclerView Тип-Безопасность с необязательными полями в классе данных для JSON Скрипт Kotlin как параметры конфигурации Gradle, не использующие расширение Приложение Android на Gradle: невозможно слить dex Какой тип языка Котлин? Чистый ООП или функциональный Полный динамический запрос базы данных Могу ли я использовать Kotlin с Codename One? коллекции kotlin, преобразующие карту в новую карту со значениями, вычисленными из оригинала Использовать группу в ConstraintLayout для прослушивания событий кликов на нескольких представлениях как использовать @jvmoverloads с интерфейсом в Kotlin Воспроизведение звуков из сырого файла в Котлине «Не удалось запустить активность» в тесте эспрессо

Kotlin: Как я могу получить фактический общий тип T в OneClass <T> во время выполнения

Друзья! Я зеленая рука на Котлине, теперь вот проблема. Теперь я хочу получить общий тип T в OneClass, вот некоторые периферийные коды.

// IDatabase.kt package com.ra abstract class IDatabase<T> { } 
 // Database1.kt import kotlin.reflect.jvm.javaType open class Database1<T>: IDatabase<T>() { val tClass = this::class.supertypes[0].arguments[0].type!!.javaType as Class<T> } 
 // Database2.kt import kotlin.reflect.jvm.javaType open class Database2<T>: IDatabase<T>() { val tClass = this::class.supertypes[0].arguments[0].type!!.javaType as Class<T> // just wrap a `object` to confort the user companion object { fun <T> getInstance(): Database2<T> { return object: Database2<T>() {} } } } 

И вот основная функция, где я тестировал три способа, пытающихся получить общий тип T, и результаты в комментарии по коду каждый.

 fun main(args: Array<String>) { val database1 = Database1<String>() println(database1.tClass.canonicalName) /** * Exception in thread "main" java.lang.ClassCastException: * sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class * at com.ra.Database1.<init>(Database1.kt:6) * at com.ra.MainKt.main(Main.kt:4) */ val database2 = object: Database1<String>() {} print(database2.tClass.canonicalName) /** * java.lang.String */ val database3 = Database2.getInstance<String>() println(database3.tClass.canonicalName) /** * Exception in thread "main" java.lang.ClassCastException: * sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class * at com.ra.Database2.<init>(Database2.kt:6) * at com.ra.Database2$Companion$getInstance$1.<init>(Database2.kt:10) * at com.ra.Database2$Companion.getInstance(Database2.kt:10) * at com.ra.MainKt.main(Main.kt:19) */ } 

Как вы видите, есть только один путь успеха – путь 2. Но это совсем не красиво. Поскольку я хочу обернуть его в статическую функцию (как это делает путь 3), он снова не удался.

Итак, вот мои вопросы:

  1. Почему возникает ошибка ClassCastException ?
  2. Есть ли более красивые способы решения проблемы? Если такое решение C # будет отличным.
  3. Я знаю, что причина проблемы в том, что JVM стирает родовой тип во время компиляции, поэтому я задаюсь вопросом (просто в любопытстве), когда это может измениться? Или, может быть, Котлин или другой язык JVM могут записывать информацию об общем типе? Если есть ПОЖАЛУЙСТА, скажите мне. У меня было достаточно стирать тип …

Solutions Collecting From Web of "Kotlin: Как я могу получить фактический общий тип T в OneClass <T> во время выполнения"

Он может работать с встроенной функцией reified

 package com.ba import kotlin.reflect.KClass abstract class IDatabase<T> { } open class Database2<T: Any>(val tClass: KClass<T>) : IDatabase<T>() { // just wrap a `object` to confort the user companion object { inline fun <reified T: Any> getInstance(): Database2<T> = Database2(T::class) } } fun main(args: Array<String>) { val databaseString = Database2.getInstance<String>() println(databaseString.tClass) val databaseInt = Database2.getInstance<Int>() println(databaseInt.tClass) } 

Выходы

 class kotlin.String class kotlin.Int