Ответ 1
Для класса с общим параметром T вы не можете сделать этого, потому что у вас нет информации о типе для T, так как JVM стирает информацию о типе. Поэтому такой код не может работать:
class Storage<T: Any> {
val snapshot: Snapshot? = ...
fun retrieveSomething(): T? {
return snapshot?.getValue(T::class.java) // ERROR "only classes can be used..."
}
}
Но вы можете сделать эту работу, если тип T подтвержден и используется внутри встроенной функции:
class Storage {
val snapshot: Snapshot? = ...
inline fun <reified T: Any> retrieveSomething(): T? {
return snapshot?.getValue(T::class.java)
}
}
Обратите внимание, что встроенная функция, если public может обращаться только к открытым членам класса. Но вы можете иметь два варианта функции: тот, который получает параметр класса, который не является встроенным, и обращается к частным внутренним элементам, а также к другой встроенной вспомогательной функции, которая выполняет переопределение из параметра inferred type:
class Storage {
private val snapshot: Snapshot? = ...
fun <T: Any> retrieveSomething(ofClass: Class<T>): T? {
return snapshot?.getValue(ofClass)
}
inline fun <reified T: Any> retrieveSomething(): T? {
return retrieveSomething(T::class.java)
}
}
Вы также можете использовать KClass
вместо Class
, чтобы вызывающие абоненты, которые являются только Kotlin, могут просто использовать MyClass::class
вместо MyClass::class.java
Если вы хотите, чтобы класс взаимодействовал с встроенным методом в generics (это означает, что класс Storage
хранит только объекты типа T
):
class Storage <T: Any> {
val snapshot: Snapshot? = ...
inline fun <reified R: T> retrieveSomething(): R? {
return snapshot?.getValue(R::class.java)
}
}
Ссылка на типы reified в встроенных функциях: https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters