Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

269
Vistas
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:

*If I try to check its type I get:

Cannot check for instance of erased type: 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:

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



*If I cast the it to UsesObjectPool, I get:

Type argument is not within its bounds. Expected: UsesObjectPool Found: 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
       }
    }
over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

The problem here is that you are not actually saying that T should be the implementing type (known as Self in some languages). As far as the Kotlin compiler is concerned, T can be any other type that implements UsesObjectPool<T>. This is why you can't pass it to 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 :(

Now imagine that it is EvilImplementation. it.objectPool.releaseObject would accept an Implementation, but you are giving it an EvilImplementation!

Anyway, I think you'd need to re-think your design, since Kotlin does not support Self as in some other languages.

See also a similar problem in Java.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda