Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instantiate a concrete Java class that uses recursive generics in Kotlin

Can I instantiate a concrete Java class that uses recursive generics in Kotlin, if so then how?

Details

I am trying to instantiate a Java class that uses recursive generics similar to the example below. I found a work around for wrapping the Java class in a new class, but that feels like I am sidestepping a problem that I should be able to handle directly.

Java Class With Recursive Generics

public class MyLegacyClass<T extends MyLegacyClass<T>> {
    // implementation ...
}

How it is Instantiated in Java

// In Java we just ignore the generic type...
MyLegacyClass myLegacyClass = new MyLegacyClass();

Failed Attempts to Instantiate in Kotlin

class myClass {
    // Error: One type argument expected for class...
    val x: MyLegacyClass = MyLegacyClass()

    // Still 'Error: One type argument expected for class..' You start to see the problem here. 
    val y: MyLegacyClass<MyLegacyClass<MyLegacyClass<MyLegacyClass>>> = MyLegacyClass()
}

Kotlin workaround

class MyLegacyClassWrapper : MyLegacyClass<MyLegacyClassWrapper>()

class myClass {
    val x: MyLegacyClass<MyLegacyClassWrapper> = MyLegacyClassWrapper()
}
like image 371
Mike Rylander Avatar asked Oct 15 '17 18:10

Mike Rylander


1 Answers

Can I instantiate a concrete Java class that uses recursive generics in Kotlin? if so then how?

No, you can't. The problem is related to variance.

This Java class:

public class MyLegacyClass<T extends MyLegacyClass<T>> {}

is equal to this Kotlin class:

class MyLegacyClass<T : MyLegacyClass<T>>

that is invariant in its parameter T. You would need instead a covariant type, so, in this case:

class MyLegacyClass<out T : MyLegacyClass<T>>

But you can't do it without creating a new Kotlin class due to Java interoperability.

I would move the class MyLegacyClass to Kotlin covariant in its parameter T if possible, otherwise, your approach is correct.

like image 133
Giorgio Antonioli Avatar answered Oct 13 '22 01:10

Giorgio Antonioli