generics - Star 投影集合中的特定 KClass
问题描述
我正在尝试构建一个外部模块可以注册的同步类,但我无法使泛型部分工作。
外部模块将SynchronizationBundle<SynchronizableType>
在 a 上注册Synchronizator
,然后应该处理同步。
interface Synchronizable<T : Synchronizable<T>>
object SynchronizationBundles {
val bundles: MutableMap<KClass<*>, SynchronizableBundle<*>> = mutableMapOf()
fun <T : Synchronizable<T>> register(kClass: KClass<T>, bundle: SynchronizableBundle<T>) {
bundles[kClass] = bundle
}
@Suppress("UNCHECKED_CAST")
operator fun <T: Synchronizable<T>> get(kClass: KClass<T>) : SynchronizableBundle<T> {
return bundles[kClass] as? SynchronizableBundle<T> ?: throw IllegalArgumentException("No bundle for ${kClass.simpleName}")
}
}
例如,在同步操作中,它应该遍历已注册的捆绑包并能够使用Synchronizable<T>
. 前面的伪代码
fun synchronize() {
bundles.forEach { bundleEntry ->
val bundle = bundles[bundleEntry.key]
val synchronizables = bundle.api.get()
remoteSynchronizables.forEach { remoteSynchronizable ->
val localSynchronizable = bundle.datastore.getByPlatformId(remoteSynchronizable.platformId)
val synchronizableToInsert = bundle.conflictStrategy.resolve(localSynchronizable, remoteSynchronizable)
synchronizableToInsert?.let {
bundle.datastore.insert(it.withUploadStatus(UploadStatus.COMPLETED))
}
}
}
}
问题是val bundle = bundles[bundleEntry.key]
返回 a SynchronizableBundle<*>
,所以我不能调用.conflictStrategy.resolve
,因为它需要 aSynchronizable<T>
例如,这是ConflictStrategy
定义。Api 和 Datastore 遵循相同的模式
interface ConflictStrategy<T : Synchronizable<T>>
这甚至可能吗?我敢肯定我不是第一个尝试这种方法的人。
如果我能以某种方式调用val bundle = bundles[MySynchronizable::class]
我会得到一个SynchronizableBundle<MySynchronizable>
,但我没有成功地做到这一点。此外,可以使用的类型Synchronizator
将在外部模块中,所以我什至不知道构建特定的KClass
是否可行。
使用高阶函数可能会让我的生活更轻松,而且这个 Synchronizator 可能与类型无关,但我没有尝试过。
谢谢!
解决方案
在下文中,我稍微简化了代码以演示如何从外部使用此捆绑管理器:
object Bundles{
private val bundles: MutableMap<KClass<*>, Bundle<*>> = mutableMapOf()
fun <T> register(c: KClass<T>, b: Bundle<T>){
bundles[c]= b
}
operator fun <T> get(kClass: KClass<T>) : Bundle<T> {
return bundles[kClass] as? Bundle<T> ?: throw IllegalArgumentException("No bundle for ${kClass.simpleName}")
}
}
fun main(args: Array<String>) {
Bundles.register(String::class, Bundle())
Bundles.register(Int::class, Bundle())
Bundles.register(Number::class, Bundle())
val stringBundle = Bundles[String::class]
val intBundle = Bundles[Int::class]
val numBundle = Bundles[Number::class]
}
你已经注意到这行得通。现在,您正在尝试循环bundles
内部的SynchronizationBundles
. 此时您无法知道已添加了什么bundles
,因此无法从中获取具体实例。恐怕您必须研究其他方法。
推荐阅读
- vue.js - Vue 3 从 vue-router 访问应用程序级别提供的实例
- java - 捕获特定的文本共享意图
- amazon-s3 - Amazon S3 - 路由 53 - 重定向到 google 站点 - 掩码 URL
- c++ - 如何避免 Microsoft C26451(算术溢出)警告
- android - 在 cameraView 活动上方显示文本
- google-apps-script - '解析文档时出错,尝试使用不同的解析字符串',同时尝试使用 xpath 查找值
- android - 自定义android插件,如何在android stuido中打印日志
- wordpress - Woocommerce 订单结帐到 whatsapp
- kubernetes - 如何将 kubernetes nginx-ingress 路由到另一个命名空间中的仪表板
- python - 为什么嵌套循环一次有效