kotlin-generics-recursive-generic-casting擦除类型的示例失败

bis0qfac  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(384)

当我遍历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
       }
    }
mnemlml8

mnemlml81#

问题是你不是真的这么说 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 ,但编译器不知道:(
现在想象一下 itEvilImplementation . it.objectPool.releaseObject 会接受 Implementation ,但你给了它一个 EvilImplementation !
无论如何,我认为你需要重新考虑你的设计,因为kotlin不支持 Self 就像其他语言一样。
另请参见java中的类似问题。

相关问题