kotlin - 无重复的 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) {
有没有办法定义这样的抽象类,这样我就不必在类定义中重复两次Payload
andPayload::class
了?
解决方案
是的,有一些反思。
在构造时,我们可以提取类型参数并将其分配给不再需要给构造函数的属性:
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
。但是,给定的代码可以检测是否不是这种情况并发出警告(在运行时)。在这种情况下,有以下解决方案:
MySubscriber
回退到提供重复的论点(基本上是你已经拥有的)- 的直接超类
MySubscriber
可以提供类似的检测机制
B)每次MySubscriber
创建实例时都调用反射代码。在某些情况下这可能太慢了,但对许多人来说这是没有问题的。
推荐阅读
- javascript - 点击 div 专注于输入
- css - 这些 W3C CSS 验证警告是关于什么的?
- javascript - 将 ASP.NET CORE Tag Helper 实现到 Javascript
- c - c - 每个线程的进度
- ios - 从常量文件填充到 Info.plist 中的动态值
- scala - 使用超过 10 个参数创建 UDF
- crystal-lang - Crystal lang:宏中的`block_given`?
- mysql - MYSQL 从一个包含多外键的单元格中选择数据
- angular - 如何使用 rxJS 在 Angular 2 的不同级别上同步进行多个 http 调用
- codenameone - 网络呼叫使用 setFailSilently() 在屏幕上显示错误消息