java - Kotlin Generics - 递归泛型 - 转换擦除类型的实例失败
问题描述
当我遍历 Sprite 列表并检查它们是否实现 UsesObjectPool 时,由于类型擦除,我遇到了这些问题:
*如果我尝试检查它的类型,我会得到:
无法检查已擦除类型的实例:UsesObjectPool
if(it is UsesObjectPool<Sprite>)
{
it.objectPool.releaseObject(it)
}
- 如果我使用通配符 * 进行检查,它表示:
“必填参数Nothing,找到Sprite & UsesObjectPool:
if(it is UsesObjectPool<*>)
{
it.objectPool.releaseObject(it)
}
*如果我将它转换为 UsesObjectPool,我会得到:
类型参数不在其范围内。预期:UsesObjectPool 发现:Sprite
if(it is UsesObjectPool<*>)
{
(it as UsesObjectPool<Sprite>).objectPool.releaseObject(it)
}
泛型类和接口:
interface UsesObjectPool<T> where T :UsesObjectPool<T>, T : Sprite
{
val objectPool: BaseObjectPool<T>
}
abstract class BaseObjectPool<T> where T : UsesObjectPool<T>, T : Sprite
{
fun releaseObject(instance: T)
{
//Implementation
}
}
解决方案
这里的问题是您实际上并没有说应该是实现类型(在某些语言中T
称为)。Self
就 Kotlin 编译器而言,T
可以是任何其他实现UsesObjectPool<T>
. 这就是为什么你不能传递it
给releaseObject
.
这是一个例子:
class EvilObjectPool<T>: BaseObjectPool<T>() where T : UsesObjectPool<T>, T : Sprite
class Implementation : Sprite(), UsesObjectPool<Implementation> {
override val objectPool: BaseObjectPool<Implementation>
get() = EvilObjectPool()
}
class EvilImplementation : Sprite(), UsesObjectPool<Implementation> {
override val objectPool: BaseObjectPool<Implementation>
get() = EvilObjectPool()
}
请注意,这会编译. 一般来说,我们人类认识到这种“自绑定泛型”模式,并且永远不会写类似的东西EvilImplementation
,但编译器不知道:(
it
现在想象一下EvilImplementation
。it.objectPool.releaseObject
会接受一个Implementation
,但你给它一个EvilImplementation
!
无论如何,我认为你需要重新考虑你的设计,因为 Kotlin 不像Self
其他一些语言那样支持。
另请参阅Java 中的类似问题。
推荐阅读
- javascript - 反应全局变量未在传递给子组件的函数内部更新
- java - R8:IR 转换期间出现 NullPointerException
- java - java中的基本for循环和数据存储
- php - 找不到 Ratchet 的 vendor/autoload.php
- azure - Azure Functions - 注入的 ILogger
日志没有出现 - javascript - 使用jQuery动画覆盖body标签的背景颜色
- android - 如何在 Android 主屏幕上显示自定义对话框?科特林
- php - 我对 MySQL 中的“UPDATE”命令有疑问
- python - 返回一个由函数调用的 2 个参数组合的新元组
- java - 一个 NetBeans 项目可以加载 .dll,但另一个抛出“无法在 IA 32 位平台上加载 AMD 64 位 .dll”