Kotlin: devuelve una interfaz genérica

En Kotlin, estoy tratando de comstackr lo siguiente:

  1. dada una interfaz con types generics (Impresora)
  2. y dos implementaciones de esa interfaz (DogPrinter y CatPrinter)
  3. devolver una de las impresoras, de acuerdo con una variable externa (AnimalType)

El siguiente código no se comstack, porque se requiere un tipo en: fun getMapper(animalType: AnimalType): Printer

Intenté usar <Any> o <*> pero no tuve éxito. ¿Alguien puede ayudar?

(fácil de ver el error copyndo el código siguiente en https://try.kotlinlang.org)

 enum class AnimalType { CAT, DOG } class Dog class Cat interface Printer<in T> { fun mapToString(input: T): String } class DogPrinter : Printer<Dog> { override fun mapToString(input: Dog): String { return "dog" } } class CatPrinter : Printer<Cat> { override fun mapToString(input: Cat): String { return "cat" } } private fun getMapper(animalType: AnimalType): Printer { return when(animalType) { AnimalType.CAT -> CatPrinter() AnimalType.DOG -> DogPrinter() } } fun usage_does_not_compile() { getMapper(AnimalType.DOG) .mapToString(5) } 

Solutions Collecting From Web of "Kotlin: devuelve una interfaz genérica"

He modificado tu código un poco. La function getMapper está ahora en inline con un tipo genérico reified , lo que hace que la llamada sea bastante legible en getMapper<Dog>() .

Lea sobre reified aquí: ¿Qué hace realmente la palabra key reified en Kotlin?

 private inline fun <reified T> getMapper(): Printer<T> { when (T::class) { Cat::class -> return CatPrinter() as Printer<T> Dog::class -> return DogPrinter() as Printer<T> } throw IllegalArgumentException() } fun main(args: Array<String>) { println(getMapper<Dog>().mapToString(Dog())) println(getMapper<Cat>().mapToString(Cat())) } 

La cosa cosificada ni siquiera es necesaria en realidad, pero hace que el lado del cliente sea más legible. Alternativamente, también puede pasar la class como argumento a la function getMapper . La parte realmente importante es hacer esto genérico . Los moldes no controlados no son muy buenos, pero parecen estar seguros aquí.

Kotlin no tiene types brutos, por lo que no puede devolver la Printer desde getMapper . Puede devolver Printer<*> , hacer que getMapper genérico o cambiar su estructura de inheritance para que tenga un super tipo común.

La Printer<*> regresa Printer<*> funciona bien. Pero en realidad no es útil porque no se puede llamar a mapToString(Dog()) (supongo que mapToString(5) es un error tipográfico) y es algo bueno: si se compiló entonces

 getMapper(AnimalType.CAT).mapToString(Dog()) 

también tendría que comstackrse, porque el tipo de devolución solo puede depender del tipo de argumento, no del valor , y AnimalType.CAT y AnimalType.DOG tienen el mismo tipo. Hay algunos idiomas que lo permiten, pero Kotlin no es uno de ellos.