Confusión con los generics de Kotlin

Soy nuevo en Kotlin y estoy tratando de escribir código que hace algo bastante simple, sin embargo, no puedo entender cómo usar los generics para que funcione.

Tengo un rasgo de Handler que representa un controller para las cosas. No puedo cambiar el código de un controller ya que proviene de una biblioteca .

 trait Handler<T> { fun handle(result: T) } 

Todo el código a continuación está bajo mi control –

User es una class abierta que tiene subclasss como AdminUser y GuestUser etc.

Un rasgo llamado AdminUserAction hace algo para crear una list de administradores de usuarios y luego pasa la list a un controller para List<AdminUser>

 trait AdminUserAction { fun then(handler: Handler<List<AdminUser>>) } 

Ahora quiero pasar a AdminUserAction un controller para el User lugar de AdminUser . Digamos que el controller simplemente registra los nombres de los usuarios y no hace nada con las properties específicas del administrador.

 fun doIt(action: AdminUserAction, printAllNames: Handler<List<User>>) { action.then(printAllNames) } 

Sin embargo, este código me da un TypeMismatch .

Dado que Handler es del tipo List<T> y es inmutable, el código anterior debe ser completamente seguro, sin embargo, el comstackdor no puede resolverlo.

Si tuviera acceso al código para Handler, podría hacer lo siguiente y funcionaría:

 trait Handler<in T> { fun handle(result: T) } 

Sin embargo, como dije antes, no puedo modificar Handler ya que proviene de una biblioteca. Además, parece raro tener que hacer esto porque el tipo de controller es completamente general y debería poder usarse también para otros types de manipuladores.

Intenté subclasificar a Handler y usar eso:

 trait ListHandler<in T>: Handler<List<T>> { } 

Sin embargo, ahora recibo un error que dice "El parámetro T se declara como 'in', pero ocurre en la position 'invariante' en Handler>"

Lo intenté –

 trait ListHandler<in T>: Handler<List<in T>> { } 

Pero eso me da más errores.

¿Por qué es esto tan confuso? ¿Y cómo puedo usar los generics para que el código anterior funcione?

Editar:

Puedo hacerlo funcionar escribiendo una function genérica que convierta un Handler<List<User>> en Handler<List<AdminUser>>

 fun <T: User> fromGeneric(handler: Handler<User>): Handler<T> { return object: Handler<T> { override fun handle(result: List<T>) { handler.handle(result) } } } 

Y entonces –

 fun doIt(action: AdminUserAction, printAllNames: Handler<List<User>>) { action.then(fromGeneric(printAllNames)) } 

Pero, esto parece tan inútil. Mire especialmente el cuerpo de la function de conversión de fromGeneric . ¡No está haciendo nada ! Sin embargo, tengo que pasar por el rigamarole de usarlo siempre para satisfacer los types.

¿Hay una mejor manera? ¿Es técnicamente posible hacer el comstackdor de Kotlin más inteligente para que este tipo de malabarismos no sea necesario?

Hay un par de soluciones:

Cambie la definición de AdminUserAction a

 trait AdminUserAction { fun then(handler: Handler<in List<AdminUser>>) } 

o cambie la definición de AdminUserAction a

 trait AdminUserAction { fun then(handler: Handler<List<User>>) } 

o simplemente echa printAllNames como este

 fun doIt(action: AdminUserAction, printAllNames: Handler<List<User>>) { action.then(printAllNames as Handler<List<AdminUser>>) }