首页 > 解决方案 > 如何获取类型参数的类名?

问题描述

我有一个基类:

abstract class JSONDeserializationStrategy<T : Any>: DeserializationStrategy<T> {
    protected abstract fun parse(json: JsonObject): T

    protected abstract fun getSerializationException(): SerializationException

}

然后是派生类

class MyClassParserDeserializationStrategy : JSONDeserializationStrategy<MyClass>() {

    override val descriptor: SerialDescriptor 
               = buildClassSerialDescriptor("MyClass")

    override fun getSerializationException(): SerializationException 
               = throw SerializationException("Invalid JSON received for MyClass.")

我如何将属性descriptor和方法getSerializationException从派生类移动到基类中,因为它们只能通过提供它们的名称作为字符串来“适应”?我试图做一些事情,T::class.java.simpleName as String但没有奏效。做这个的最好方式是什么?

标签: kotlin

解决方案


正如@Tenfour04 解释的那样,T它已被删除,因此无法直接访问。但是,只要JSONDeserializationStrategy提供的子类T作为特定的类/类型,就可以通过一些反射巫术来获取它:

fun main() {
    val strategy = MyClassParserDeserializationStrategy()
    println(strategy.descriptor.serialName)  // MyClass
}

abstract class JSONDeserializationStrategy<T : Any>: DeserializationStrategy<T> {
    protected val type: KType = this::class.supertypes
        .first { it.classifier == JSONDeserializationStrategy::class }
        .arguments[0].type!!

    @Suppress("UNCHECKED_CAST")
    protected val typeClass = requireNotNull(type.classifier as? KClass<T>) {
        "T is unknown"
    }

    override val descriptor: SerialDescriptor = buildClassSerialDescriptor(typeClass.simpleName!!)

    fun getSerializationException(): SerializationException =
        throw SerializationException("Invalid JSON received for ${typeClass.simpleName!!}.")

    ...
}

我不是 100% 确定,但我相信两者type!!都是simpleName!!安全的,它们不能为空。

T此外,如果真的完全擦除且未知,它将无法工作,例如:

val strategy = GenericParserDeserializationStrategy<MyClass>() // exception

type出于这个原因,打开/属性进行覆盖是有意义typeClass的,因此通用的非抽象子类可以提供自己的获取方式T。但是,我们可能需要将大多数属性的初始化移到构造函数之外。


推荐阅读