我是相对较新的Kotlin,泛型让我头疼.我有一个由以下material 组成的架构:

  • 几个数据类
  • 处理数据的通用接口
  • 每种数据类型处理接口的实现
  • 包含要处理的数据及其相应处理器的通用处理作业(job)类
  • 一个全局(单例)处理器,它实现处理接口,接受处理作业(job),并将处理委托给作业(job)处理器.它根本不关心数据本身.

简化的代码如下所示

class DataOne
class DataTwo

interface DataProcessor<in T> {
    fun process(o: T)
}

class DataOneProcessor: DataProcessor<DataOne> {
    override fun process(o: DataOne) = println("Processing DataOne")
}

class DataTwoProcessor: DataProcessor<DataTwo> {
    override fun process(o: DataTwo) = println("Processing DataTwo")
}

class ProcessingJob<T>(val data: T, val processor: DataProcessor<T>)

object GlobalProcessor: DataProcessor<ProcessingJob<Any>> {

    override fun process(job: ProcessingJob<Any>) = job.processor.process(job.data)

}

fun main() {
    GlobalProcessor.process(ProcessingJob(DataOne(), DataOneProcessor()))
}

在Main函数中,我得到一个编译器错误

Type mismatch.
Required: ProcessingJob<Any>
Found: ProcessingJob<DataOne>

我理解为什么会发生这种情况:DataOneDataProcessor,被视为AnyDataProcessor,可能会被要求处理DataTwo,出于类型安全考虑,这是不允许的.

你能给我一些建议吗?怎样修改才能使它编译并达到所需的效果?耽误您时间,实在对不起!

推荐答案

这里有两个问题.

首先,Any实际上不是最高级别的类型.Any表示不为空,但T不受约束,这意味着它可以是可为空的类型.在本例中,您可以使用*,也可以将类型指定为Any?.

GlobalProcessor的签名更改为:

object GlobalProcessor: DataProcessor<ProcessingJob<*>> {
    override fun process(job: ProcessingJob<*>): ...

第二个问题是,process的实现无法利用来自job的通用信息来知道job.processorjob.data是兼容的.它只看到两个未知类型的对象.要让它知道它们共享一个兼容的类型,您需要将该类型捕获为类型变量.我们不能向现有方法添加泛型类型参数,因为它必须与接口方法的签名匹配,但我们可以添加一个引入泛型参数的新私有方法.

以下是GlobalProcessor个需要更改的内容.

object GlobalProcessor: DataProcessor<ProcessingJob<*>> {
    override fun process(job: ProcessingJob<*>) = processGeneric(job)
    private fun <T> processGeneric(job: ProcessingJob<T>) = job.processor.process(job.data)
}

Kotlin相关问答推荐

为什么在Spring中,对事务性方法调用的非事务方法调用仍然在事务中运行?

在Jetpack Compose中创建波浪式文本动画:顺序中断问题

Groovy Gradle文件的Kotlin类似功能

从 Kotlin 的父类获取函数注解

按钮无法在 Android Studio 上打开新活动

使用 Compose for Desktop Bundle 文件

正则表达式 FindAll 不打印结果 Kotlin

kotlin 单例异常是好是坏?

在 APK META-INF/library_release.kotlin_module 中复制的重复文件

如何从 Firestore 查询中排除元素?

在 Scaffold Jetpack Compose 内的特定屏幕上隐藏顶部和底部导航器

片段内的 Kotlin 按钮 onClickListener 事件

从片段(fragment)中的点击事件启动协同程序

Kotlin 接口属性:只需要公共 getter 而没有公共 setter

未解决的参考 dagger 2 + kotlin + android gradle

在 Kotlin 函数上使用 Mokito anyObject() 时,指定为非 null 的参数为 null

Kotlin 警告:Conditional branch result of type ... is implicity cast of Any?

判断EditText是否为空kotlin android

Kotlin - 如果不为空,则使用修改后的 Obj props 覆盖 Obj props

尾随 lambda 语法(Kotlin)的目的是什么?