Variância no Local da Declaração
in e out
Variância no Local da Declaração é uma aula grátis de Kotlin Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Kotlin Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Kotlin Academy inclui 4 aulas no total.
O problema da variância
Uma List<String> é um tipo de List<Any>? Às vezes sim, às vezes não. A variância descreve como os tipos genéricos se relacionam quando seus parâmetros de tipo se relacionam. O Kotlin usa out e in para expressar isso.
Invariância por padrão
Por padrão, os genéricos são invariantes: Box<String> NÃO é um Box<Any>, embora String seja um subtipo de Any. Isso impede operações inseguras.
class Box<T>(val value: T)
fun main() {
val strBox = Box("hi")
// val anyBox: Box<Any> = strBox // would not compile
println(strBox.value)
}Covariância com out
Marcar um parâmetro de tipo com out faz com que ele seja covariante: Producer<String> se torna um subtipo de Producer<Any>. O tipo só pode aparecer em posições de saída, como tipos de retorno.
class Producer<out T>(private val item: T) {
fun produce(): T = item
}
fun main() {
val strProducer: Producer<String> = Producer("hello")
val anyProducer: Producer<Any> = strProducer
println(anyProducer.produce())
}Por que out é seguro
Se uma classe apenas produz, ou retorna, T e nunca o consome, tratar uma Producer<String> como uma Producer<Any> é seguro, pois cada String que ela retorna também é um Any.
out na biblioteca padrão
A List<out E> somente leitura do Kotlin é covariante, por isso uma List<String> pode ser usada onde uma List<Any> é esperada.
fun printAll(items: List<Any>) {
items.forEach { println(it) }
}
fun main() {
val names: List<String> = listOf("Ann", "Bob")
printAll(names)
}Contravariância com in
Marcar um parâmetro de tipo com in faz com que ele seja contravariante: Consumer<Any> se torna um subtipo de Consumer<String>. O tipo só pode aparecer em posições de entrada, como parâmetros.
class Consumer<in T> {
fun consume(item: T) {
println("Consumed $item")
}
}
fun main() {
val anyConsumer: Consumer<Any> = Consumer()
val strConsumer: Consumer<String> = anyConsumer
strConsumer.consume("hi")
}Por que in é seguro
Um consumidor que aceita Any certamente pode aceitar uma String. Portanto, uma Consumer<Any> pode ser usada em qualquer lugar onde uma Consumer<String> seja necessária.
A mnemônica PECS
Lembre-se de Producer Extends, Consumer Super ou, nos termos do Kotlin: out para produtores, isto é, saída, e in para consumidores, isto é, entrada. Um tipo que apenas produz T usa out; um tipo que apenas recebe T usa in.
Combinando in e out
Um parâmetro de tipo usado tanto para entrada quanto para saída, como em uma lista mutável, deve permanecer invariante. Os tipos Function mostram os dois casos: os parâmetros são in e o retorno é out.
fun main() {
val f: (Number) -> Int = { it.toInt() }
val g: (Int) -> Number = f
println(g(3.0.let { Number::class; 5 }))
}Variância no local da declaração significa um único lugar
A variância no local da declaração é definida uma vez, na própria classe, com in/out. Todas as utilizações da classe recebem a variância automaticamente, ao contrário do Java, em que você repete os curingas em cada utilização.
Escolhendo in ou out
Pergunte: esta classe apenas produz T, usando out; apenas consome T, usando in; ou faz as duas coisas, devendo permanecer invariante? Associar o modificador à função da classe torna seus tipos genéricos flexíveis e seguros.
Verificação rápida
O que o modificador out indica?
Recapitulação
Por padrão, os genéricos são invariantes. Use out para obter covariância quando um tipo apenas produz valores e in para obter contravariância quando ele apenas consome valores. Lembre-se: produtores usam out, consumidores usam in. Em seguida, você aplicará a variância no ponto de uso com projeções de tipo.
Perguntas Frequentes
A aula “Variância no Local da Declaração” é grátis?
Sim — o texto completo de “Variância no Local da Declaração” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Kotlin Academy, atualize para CoddyKit PRO. O curso de Kotlin Academy inclui 4 aulas no total.
O que vou aprender em “Variância no Local da Declaração”?
in e out Você pratica Kotlin Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Kotlin Academy?
Nenhuma experiência prévia é necessária. Kotlin Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “Variância no Local da Declaração”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Kotlin Academy?
Sim. Cada aula de Kotlin Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Funções e Classes Genéricas
- Variância no Local da Declaração
- Variância no Local de Uso
- Restrições Genéricas