2017-10-15 51 views
4

Puis-je instancier une classe Java concrète qui utilise des génériques récursifs dans Kotlin, si oui, comment?Instancier une classe Java concrète qui utilise des génériques récursifs dans Kotlin

Détails

Je suis en train de instancier une classe Java qui utilise génériques récursives similaire à l'exemple ci-dessous. J'ai trouvé un moyen de contourner la classe Java dans une nouvelle classe, mais j'ai l'impression de contourner un problème que je devrais pouvoir gérer directement.

classe Java avec récursif Generics

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

Comment il est instancié en Java

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

tentatives ratées de instancier dans 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 solution

class MyLegacyClassWrapper : MyLegacyClass<MyLegacyClassWrapper>() 

class myClass { 
    val x: MyLegacyClass<MyLegacyClassWrapper> = MyLegacyClassWrapper() 
} 
+1

L'instancier dans Java de cette façon est une mauvaise idée, voir https://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html. –

+0

@AlexeyRomanov I vous affirmant que l'instanciation d'un objet générique en utilisant des types bruts est une mauvaise idée? (Si oui, je suis d'accord, je veux juste m'assurer que je comprends votre commentaire) –

+1

Oui (comme un cas spécifique d'une déclaration plus générale que l'utilisation de types bruts est une mauvaise idée sauf si vous avez des exigences pour maintenir la compatibilité avec Java Code -5/JVM). –

Répondre

4

Puis-je instancier une classe concrète de Java qui utilise des génériques récursifs dans Kotlin? si oui alors comment?

Non, vous ne pouvez pas. Le problème est lié à la variance.

Cette classe Java:

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

est égal à cette classe Kotlin:

class MyLegacyClass<T : MyLegacyClass<T>> 

qui est invariant dans son paramètre T. Vous auriez besoin au lieu d'un type covariant , donc, dans ce cas:

class MyLegacyClass<out T : MyLegacyClass<T>> 

Mais vous ne pouvez pas le faire sans créer une nouvelle classe Kotlin en raison de l'interopérabilité Java.

Je voudrais déplacer la classe MyLegacyClass à covariant Kotlin dans son paramètre T si possible, sinon, votre approche est correcte.

+0

Si elle était convertie en Kotlin et utilisait la signature 'class MyLegacyClass >', à quoi ressemblerait l'instanciation? –

+3

@MikeRylander il va ressembler à: 'val x = MyLegacyClass >()' –

+1

Cela fonctionne, merci! –