[英]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)
}
"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
.现在想象
it
是EvilImplementation
。 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.