简体   繁体   English

Kotlin 泛型 - 递归泛型 - 转换擦除类型的实例失败

[英]Kotlin Generics - recursive generic - casting the instance of erased type fails

When I iterate over a list of Sprites and check whether they implement UsesObjectPool or not, I am encountering these problems due to type erasure:当我遍历 Sprite 列表并检查它们是否实现 UsesObjectPool 时,由于类型擦除,我遇到了这些问题:

*If I try to check its type I get: *如果我尝试检查它的类型,我会得到:

Cannot check for instance of erased type: UsesObjectPool无法检查已擦除类型的实例:UsesObjectPool

  if(it is UsesObjectPool<Sprite>)
        {
            it.objectPool.releaseObject(it)
        }



  • If I use the wildcard * to check, it says that:如果我使用通配符 * 来检查,它说:

"required parameter Nothing, found Sprite & UsesObjectPool: ”必填参数Nothing,找到Sprite & UsesObjectPool:

  if(it is UsesObjectPool<*>)
            {
                it.objectPool.releaseObject(it)
            }



*If I cast the it to UsesObjectPool, I get: *如果我将它转换为 UsesObjectPool,我会得到:

Type argument is not within its bounds.类型参数不在其范围内。 Expected: UsesObjectPool Found: Sprite预期:UsesObjectPool 发现:Sprite

 if(it is UsesObjectPool<*>)
            {
                (it as UsesObjectPool<Sprite>).objectPool.releaseObject(it)
            }



The generic class and interface:泛型类和接口:

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
       }
    }

The problem here is that you are not actually saying that T should be the implementing type (known as Self in some languages).这里的问题是您实际上并不是说T应该是实现类型(在某些语言中称为Self )。 As far as the Kotlin compiler is concerned, T can be any other type that implements UsesObjectPool<T> .就 Kotlin 编译器而言, T可以是实现UsesObjectPool<T>任何其他类型。 This is why you can't pass it to releaseObject .这就是为什么你不能将it传递给releaseObject

Here is an example:下面是一个例子:

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()

}

Notice that this compiles .请注意,这会编译. Generally we as humans recognise this "self-bound generics" pattern, and will never write something like EvilImplementation , but the compiler doesn't know that :(通常我们作为人类认识到这种“自绑定泛型”模式,并且永远不会写类似EvilImplementation东西,但编译器不知道:(

Now imagine that it is EvilImplementation .现在想象itEvilImplementation it.objectPool.releaseObject would accept an Implementation , but you are giving it an EvilImplementation ! it.objectPool.releaseObject会接受一个Implementation ,但你给它一个EvilImplementation

Anyway, I think you'd need to re-think your design, since Kotlin does not support Self as in some other languages.无论如何,我认为您需要重新考虑您的设计,因为 Kotlin 不像其他语言那样支持Self

See also a similar problem in Java .另请参阅Java 中的类似问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM