Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

128
Vistas
¿Qué es la palabra clave en kotlin?

No puedo entender y no pude encontrar el significado de la palabra clave en kotlin.

Puede consultar el ejemplo aquí:

 List<out T>

Si alguien puede explicar el significado de esto. Esto sera realmente apreciado.

over 4 years ago · Santiago Trujillo
7 Respuestas
Responde la pregunta

0

Recuerda así:

in es "for in put" - quieres poner (escribir) algo en él (así que es un "consumidor")

out es "for out put" - quieres sacar (leer) algo de él (así que es un "productor")

Si eres de Java,

<in T> es para entrada, así que es como <? super T> (consumidor)

<out T> es para salida, así que es como <? extends T> (productor)

over 4 years ago · Santiago Trujillo Denunciar

0

Los modificadores de varianza de entrada y out in permiten hacer que nuestros tipos genéricos sean menos restrictivos y más reutilizables al permitir la creación de subtipos.

Entendamos esto con la ayuda de ejemplos contrastantes. Usaremos ejemplos de estuches como contenedores de varias armas. Supongamos que tenemos la siguiente jerarquía de tipos:

 open class Weapon open class Rifle : Weapon() class SniperRifle : Rifle()

out produce T y conserva la subtipificación

Cuando declara un tipo genérico con un modificador de out , se llama covariante . Una covariante es productora de T , lo que significa que las funciones pueden devolver T pero no pueden tomar T como argumentos:

 class Case<out T> { private val contents = mutableListOf<T>() fun produce(): T = contents.last() // Producer: OK fun consume(item: T) = contents.add(item) // Consumer: Error }

El Case declarado con el modificador out produce T y sus subtipos:

 fun useProducer(case: Case<Rifle>) { // Produces Rifle and its subtypes val rifle = case.produce() }

Con el modificador out , se conserva el subtipo, por lo que Case<SniperRifle> es un subtipo de Case<Rifle> cuando SniperRifle es un subtipo de Rifle . Como resultado, la función useProducer() también se puede llamar con Case<SniperRifle> :

 useProducer(Case<SniperRifle>()) // OK useProducer(Case<Rifle>()) // OK useProducer(Case<Weapon>()) // Error

Esto es menos restrictivo y más reutilizable durante la producción, pero nuestra clase se vuelve de solo lectura .


in consume T e invierte la subtipificación

Cuando declara un tipo genérico con un modificador in , se llama contravariant . Una contravariante es un consumidor de T , eso significa que las funciones pueden tomar T como argumentos pero no pueden devolver T :

 class Case<in T> { private val contents = mutableListOf<T>() fun produce(): T = contents.last() // Producer: Error fun consume(item: T) = contents.add(item) // Consumer: OK }

El Case declarado con el modificador in consume T y sus subtipos:

 fun useConsumer(case: Case<Rifle>) { // Consumes Rifle and its subtypes case.consume(SniperRifle()) }

Con el modificador in , el subtipo se invierte , por lo que ahora Case<Weapon> es un subtipo de Case<Rifle> cuando Rifle es un subtipo de Weapon . Como resultado, la función useConsumer() también se puede llamar con Case<Weapon> :

 useConsumer(Case<SniperRifle>()) // Error useConsumer(Case<Rifle>()) // OK useConsumer(Case<Weapon>()) // OK

Esto es menos restrictivo y más reutilizable mientras se consume, pero nuestra clase se vuelve solo de escritura .


Invariante produce y consume T , no permite la subtipificación

Cuando declara un tipo genérico sin ningún modificador de varianza, se llama invariante . Un invariante es tanto productor como consumidor de T , lo que significa que las funciones pueden tomar T como argumentos y también pueden devolver T :

 class Case<T> { private val contents = mutableListOf<T>() fun produce(): T = contents.last() // Producer: OK fun consume(item: T) = contents.add(item) // Consumer: OK }

El Case declarado sin modificador in o out produce y consume T y sus subtipos:

 fun useProducerConsumer(case: Case<Rifle>) { // Produces Rifle and its subtypes case.produce() // Consumes Rifle and its subtypes case.consume(SniperRifle()) }

Sin el modificador in entrada o out , el subtipo no está permitido , por lo que ahora ni Case<Weapon> ni Case<SniperRifle> son un subtipo de Case<Rifle> . Como resultado, la función useProducerConsumer() solo se puede llamar con Case<Rifle> :

 useProducerConsumer(Case<SniperRifle>()) // Error useProducerConsumer(Case<Rifle>()) // OK useProducerConsumer(Case<Weapon>()) // Error

Esto es más restrictivo y menos reutilizable al producir y consumir, pero podemos leer y escribir .


Conclusión

The List en Kotlin es solo un productor. Porque se declara usando el modificador out : List<out T> . Esto significa que no puede agregarle elementos ya que add(element: T) es una función de consumo. Siempre que desee poder get() y add() elementos, use la versión invariable MutableList<T> .

¡Eso es todo! ¡Esperemos que eso ayude in comprender las entradas y out de la variación!

over 4 years ago · Santiago Trujillo Denunciar

0

Estas respuestas explican qué hace out , pero no por qué lo necesita, así que supongamos que no teníamos out en absoluto. Imagine tres clases: Animal, Cat, Dog y una función tomando una lista de Animal

 abstract class Animal { abstract fun speak() } class Dog: Animal() { fun fetch() {} override fun speak() { println("woof") } } class Cat: Animal() { fun scratch() {} override fun speak() { println("meow") } }

Dado que Dog es un subtipo de Animal , queremos usar List<Dog> como subtipo de List<Animal> , lo que significa que queremos poder hacer esto:

 fun allSpeak(animals: List<Animal>) { animals.forEach { it.speak() } } fun main() { val dogs: List<Dog> = listOf(Dog(), Dog()) allSpeak(dogs) val mixed: List<Animal> = listOf(Dog(), Cat()) allSpeak(mixed) }

Y eso está bien, el código imprimirá woof woof para los perros y woof meow para la lista mixta.

El problema es cuando tenemos un contenedor mutable. Dado que List<Animal> puede contener Dog y Cat , podemos agregar ambos a MutableList<Animal>

 fun processAnimals(animals: MutableList<Animal>) { animals.add(Cat()) // uh oh, what if this is a list of Dogs? } fun main() { val dogs: MutableList<Dog> = mutableListOf(Dog(), Dog()) processAnimals(dogs) // we just added a Cat to a list of Dogs! val d: Dog = dogs.last() // list of Dogs, so return type of .last() is Dog // but this is actually a Cat d.fetch() // a Cat can't fetch, so what should happen here? }

No puede considerar con seguridad MutableList<Dog> sea un subtipo de MutableList<Animal> porque puede hacer cosas con este último (insertar un gato) que no puede hacer con el primero.

Como un ejemplo más extremo:

 val dogs: MutableList<Dog> = mutableListOf(Dog()) val anything: MutableList<Any> = dogs // now I can add any type I want to the dogs list through the anything list anything.add("hello world")

El problema solo ocurre al agregar a la lista, no al leer de ella. Es seguro usar List<Dog> como List<Animal> porque no se puede agregar a List . Esto es lo que nos dice out . out dice "este es un tipo que emito, pero no lo tomo como nuevas entradas que consumo"

over 4 years ago · Santiago Trujillo Denunciar

0

Una buena explicación de la programación funcional en Kotlin :

Considere el siguiente código:

 sealed class List<out A> object Nil : List<Nothing>() data class Cons<out A>(val head: A, val tail: List<A>) : List<A>()

En la clase de declaración Lista, la salida delante del parámetro de tipo A es una anotación de varianza que indica que A es un parámetro covariante o “positivo” de Lista. Esto significa, por ejemplo, que Lista se considera un subtipo de Lista, suponiendo que Perro sea un subtipo de Animal. (De forma más general, para todos los tipos X e Y, si X es un subtipo de Y, entonces Lista es un subtipo de Lista). Podríamos omitir la salida delante de A, lo que haría que Lista fuera invariable en ese parámetro de tipo. Pero fíjate ahora que Nil extiende List. Nada es un subtipo de todos los tipos, lo que significa que, junto con la anotación de varianza, Nil puede considerarse una Lista, una Lista, etc., exactamente como queramos.

over 4 years ago · Santiago Trujillo Denunciar

0

Consulte el manual de thie de kotlin

El tipo Kotlin List<out T> es una interfaz que proporciona operaciones de solo lectura como size, get, etc. Al igual que en Java, hereda de Collection<T> y que a su vez hereda de Iterable<T> . La interfaz MutableList<T> agrega métodos que cambian la lista. Este patrón también es válido para Set<out T>/MutableSet<T> y Map<K, out V>/MutableMap<K, V>

Y esto,

En Kotlin, hay una forma de explicar este tipo de cosas al compilador. Esto se denomina varianza del sitio de declaración: podemos anotar el parámetro de tipo T de Source para asegurarnos de que solo lo devuelvan (produzcan) los miembros de Source<T> y nunca se consuma. Para hacer esto proporcionamos el modificador out:

 > abstract class Source<out T> { > abstract fun nextT(): T } > > fun demo(strs: Source<String>) { > val objects: Source<Any> = strs // This is OK, since T is an out-parameter > // ... }

La regla general es: cuando un parámetro de tipo T de una clase C se declara out, puede ocurrir solo en posición out en los miembros de C , pero a cambio C<Base> puede ser un supertipo de C<Derived> .

En "palabras inteligentes" dicen que la clase C es covariante en el parámetro T , o que T es un parámetro de tipo covariante. Puede pensar en C como un productor de T y NO como un consumidor de T El modificador de salida se denomina anotación de varianza y, dado que se proporciona en el sitio de declaración de parámetros de tipo, hablamos de la varianza del sitio de declaración. Esto contrasta con la variación del sitio de uso de Java donde los comodines en los usos de tipo hacen que los tipos sean covariantes.

over 4 years ago · Santiago Trujillo Denunciar

0

Con esta firma:

 List<out T>

Puedes hacerlo:

 val doubleList: List<Double> = listOf(1.0, 2.0) val numberList: List<Number> = doubleList

lo que significa que T es covariante :

cuando se declara out un parámetro de tipo T de una clase C , C<Base> puede ser con seguridad un supertipo de C<Derived> .

Esto contrasta con en , por ejemplo

 Comparable<in T>

Puedes hacerlo:

 fun foo(numberComparable: Comparable<Number>) { val doubleComparable: Comparable<Double> = numberComparable // ... }

lo que significa que T es contravariante :

cuando un parámetro de tipo T de una clase C se declara en , C<Derived> puede ser con seguridad un supertipo de C<Base> .

Otra forma de recordarlo:

Consumidor adentro , Productor afuera .

ver Variación de los genéricos de Kotlin

-----------------actualizado el 4 de enero de 2019-----------------

Para el " Consumidor dentro, Productor fuera ", solo leemos del Productor - método de llamada para obtener el resultado de tipo T; y solo escriba en el método de llamada al consumidor pasando el parámetro de tipo T.

En el ejemplo de List<out T> , es obvio que podemos hacer esto:

 val n1: Number = numberList[0] val n2: Number = doubleList[0]

Por lo tanto, es seguro proporcionar List<Double> cuando se espera List< List<Number> , por lo que List<Number> es un supertipo de List<Double> , pero no al revés.

En el ejemplo de Comparable<in T> :

 val double: Double = 1.0 doubleComparable.compareTo(double) numberComparable.compareTo(double)

Por lo tanto, es seguro proporcionar Comparable<Number> cuando se espera Comparable< Comparable<Double> , por lo que Comparable<Double> es un supertipo de Comparable<Number> , pero no al revés.

over 4 years ago · Santiago Trujillo Denunciar

0

List<out T> en Kotlin es equivalente a List<? extends T> en Java.

List<in T> en Kotlin es equivalente a List<? super T> en Java

Por ejemplo, en Kotlin puedes hacer cosas como

 val value : List<Any> = listOf(1,2,3) //since List signature is List<out T> in Kotlin
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda