首页 > 解决方案 > 无重复的 Kotlin 类泛型

问题描述

考虑一个抽象类:

abstract class PubSubSubscriber<T : Any>(private val topic: KClass<T>) : BackgroundFunction<PubSubMessage> {
    abstract fun consume(payload: T)

    override fun accept(message: PubSubMessage, context: Context) {
        val json = String(Base64.getDecoder().decode(message.data.toByteArray()))
        val payload = objectMapper.readValue(json, topic.java)
        consume(payload)
    }
}

和实施:

class MySubscriber : PubSubSubscriber<Payload>(Payload::class) {

有没有办法定义这样的抽象类,这样我就不必在类定义中重复两次PayloadandPayload::class了?

标签: kotlin

解决方案


是的,有一些反思。

在构造时,我们可以提取类型参数并将其分配给不再需要给构造函数的属性:

abstract class PubSubSubscriber<T : Any> {

    val topic: KClass<T> = extractTypeParam<T>(0).kotlin

    private fun <X> extractTypeParam(paramIdx: Int): Class<X> {
        require(PubSubSubscriber::class.java == javaClass.superclass) {
            "PubSubSubscriber subclass $javaClass should directly extend PubSubSubscriber"
        }
        @Suppress("UNCHECKED_CAST")
        return (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[paramIdx] as Class<X>
    }

    abstract fun consume(payload: T)

    override fun accept(message: PubSubMessage, context: Context) {
        val json = String(Base64.getDecoder().decode(message.data.toByteArray()))
        val payload = objectMapper.readValue(json, topic.java)
        consume(payload)
    }

请注意以下限制:

A)此解决方案仅在MySubscriber直接从 扩展时才有效PubSubSubscriber。但是,给定的代码可以检测是否不是这种情况并发出警告(在运行时)。在这种情况下,有以下解决方案:

  1. MySubscriber回退到提供重复的论点(基本上是你已经拥有的)
  2. 的直接超类MySubscriber可以提供类似的检测机制

B)每次MySubscriber创建实例时都调用反射代码。在某些情况下这可能太慢了,但对许多人来说这是没有问题的。


推荐阅读