首页 > 解决方案 > 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
       }
    }

标签: javaandroidkotlingenerics

解决方案


这里的问题是您实际上并没有说应该是实现类型(在某些语言中T称为)。Self就 Kotlin 编译器而言,T可以是任何其他实现UsesObjectPool<T>. 这就是为什么你不能传递itreleaseObject.

这是一个例子:

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现在想象一下EvilImplementationit.objectPool.releaseObject会接受一个Implementation,但你给它一个EvilImplementation

无论如何,我认为你需要重新考虑你的设计,因为 Kotlin 不像Self其他一些语言那样支持。

另请参阅Java 中的类似问题


推荐阅读