Kotlin: приведение объекта к универсальному классу

#android #generics #kotlin #interface #fragment

#Android #универсальные #kotlin #интерфейс #фрагмент

Вопрос:

Как получить тип универсального класса и привести к нему объект?

Я хочу использовать эту функцию для передачи класса интерфейса:

 protected fun <T> getInteraction(): T {
        return when {
            context is T -> context
            parentFragment is T -> parentFragment as T
            else -> throw IllegalArgumentException("not implemented interaction")
        }
    }
  

и использовать его как:

  private var interaction: ISigninInteraction? = null

 override fun onAttach(context: Context?) {
        super.onAttach(context)
        interaction = getInteraction<ISigninInteraction>()

 }
  

Ответ №1:

В Kotlin, Java и JVM типы стираются при реализации обобщений. Универсальные объекты не видны на уровне байт-кода. Это означает, что вы не можете использовать параметры типа, например T , непосредственно в коде функции.

Kotlin добавляет поддержку reified дженериков, которая помогает здесь. Вы можете объявить функцию следующим образом

 inline fun <reified T> getIt() : T {
  ...
}
  

С помощью reified и inline можно будет привести к T и вернуть его.
https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters

Вторая альтернатива — следовать практике Java — добавить Class<T> параметр в функцию и использовать Class#cast для приведения к T вместо этого.

Вы можете объединить reified inline функцию с подходом, подобным:

 inline fun <reified T> getIt() = getIt(T::class.java)