Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

272
Views
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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!