Z powodu type erasure, rzeczywiste argumenty ogólne nie mogą zostać uzyskane za pomocą tokena klasy generycznej za pomocą T::class
. Różne obiekty klasy muszą mieć ten sam token klasy, dlatego nie może zawierać rzeczywistych argumentów ogólnych.
Ale istnieje technika o nazwie super type tokens, która może podać rzeczywiste argumenty typu w przypadku, gdy typ jest znany w czasie kompilacji (dotyczy to reifikowanych generycznych w Kotlin z powodu wstawiania).
Podstęp polega na tym, że kompilator zachowuje rzeczywiste argumenty typu dla nie ogólnej klasy wywodzącej się z klasy ogólnej (wszystkie jej wystąpienia będą miały te same argumenty, dobre objaśnienie, here). Są one dostępne przez instancję clazz.genericSuperClass.actualTypeArguments
instancji Class<*>
.
Biorąc pod uwagę wszystko, co można napisać klasy util tak:
abstract class TypeReference<T> : Comparable<TypeReference<T>> {
val type: Type =
(javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0]
override fun compareTo(other: TypeReference<T>) = 0
}
wyjaśnione Jackson TypeReference który używa tego samego podejścia. Moduł Jacksona Kotlina uses it dotyczący reifikacji generyków.
Następnie w funkcji rolkach z A reified generycznych TypeReference
potrzeby na podklasy (e object expression się go), a następnie jego type
mogą być użyte.
przykład:
inline fun <reified T: Any> printGenerics() {
val type = object : TypeReference<T>() {}.type
if (type is ParameterizedType)
type.actualTypeArguments.forEach { println(it.typeName) }
}
printGenerics<HashMap<Int, List<String>>>()
:
java.lang.Integer
java.util.List<? extends java.lang.String>
wymiana ** ** Każdy z odpowiedni interfejs, i pracować z interfejsem :) –