Kotlin Academy · Lezione

Varianza use-site

Proiezioni di tipo

Lezione 3 di 413 passaggi

Varianza use-site è una lezione Kotlin Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Kotlin Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Kotlin Academy include 4 lezioni in totale.

Varianza sul sito di utilizzo

A volte una classe generica è complessivamente invariante, ma una funzione specifica produce soltanto il tipo oppure lo consuma soltanto. La varianza sul sito di utilizzo, detta anche proiezione di tipo, applica out o in direttamente nel punto in cui viene usato un tipo.

Perché usare la varianza sul sito di utilizzo

Una classe invariante come MutableList<T> non può essere resa covariante nella dichiarazione perché legge e scrive entrambe su T. Tuttavia, una funzione specifica potrebbe limitarsi a leggere dalla classe, e le proiezioni consentono di esprimerlo in modo sicuro.

Proiezione out

Scrivere Array<out T> come tipo di parametro produce una vista covariante: è possibile leggere T, ma non scriverlo. In questo modo si può passare un Array<String> dove è previsto un Array<out Any>.

fun printArray(items: Array<out Any>) {
    for (item in items) println(item)
}

fun main() {
    val names: Array<String> = arrayOf("Ann", "Bob")
    printArray(names)
}

Solo lettura

Con una proiezione out, il compilatore consente le letture, cioè l'output, ma vieta le scritture, cioè l'input, perché una scrittura potrebbe violare la sicurezza dei tipi dell'array originale.

Proiezione in

Scrivere Array<in T> produce una vista controvariante: è possibile scrivere T al suo interno, ma le letture restituiscono Any?. In questo modo si possono accettare array di T o di qualsiasi suo supertipo.

fun fill(dest: Array<in Int>, value: Int) {
    for (i in dest.indices) dest[i] = value
}

fun main() {
    val numbers: Array<Number> = arrayOf(0, 0, 0)
    fill(numbers, 7)
    println(numbers.toList())
}

Solo scrittura

Con una proiezione in è possibile scrivere valori di tipo T, cioè l'input, ma il tipo degli elementi viene visto come il tipo più generale per le letture, poiché il tipo effettivo degli elementi potrebbe essere un supertipo qualsiasi.

Proiezioni e sito di dichiarazione

La varianza sul sito di dichiarazione, come in class Box<out T>, si applica ovunque venga usata la classe. Le proiezioni sul sito di utilizzo, come Box<out T> come parametro, si applicano solo in quel punto. Usi le proiezioni quando la classe stessa deve rimanere invariante.

La proiezione a stella

Quando il tipo del parametro non è importante, utilizzi la proiezione a stella *. List<*> indica una lista di tipo sconosciuto; è possibile leggere gli elementi come il limite superiore, ma non è possibile scrivervi in modo sicuro.

fun printSize(collection: List<*>) {
    println("Size: ${collection.size}")
}

fun main() {
    printSize(listOf(1, 2, 3))
    printSize(listOf("a", "b"))
}

Limiti della proiezione a stella

Con * è comunque possibile chiamare i membri indipendenti dal tipo, come size, e leggere gli elementi come Any?, ma non è possibile aggiungere elementi perché il tipo reale è sconosciuto.

fun main() {
    val unknown: List<*> = listOf("x", "y")
    val first: Any? = unknown.first()
    println(first)
}

Scelta della proiezione

Utilizzi out T quando una funzione esegue solo letture, in T quando esegue solo scritture e * quando il tipo esatto non è rilevante. Queste proiezioni rendono utilizzabili le classi invarianti in modo flessibile e sicuro dal punto di vista dei tipi.

Relazione con i wildcard di Java

Le proiezioni Kotlin out T e in T corrispondono ai wildcard Java ? extends T e ? super T. Se conosce i generics di Java, le proiezioni Le risulteranno familiari.

Verifica rapida

Che cosa è possibile fare con un parametro tipizzato come Array<out Any>?

Riepilogo

La varianza a livello d'uso applica proiezioni out (sola lettura) o in (sola scrittura) in un punto specifico, e utilizza * come proiezione a stella quando il tipo è sconosciuto. In questo modo le classi invarianti diventano flessibili senza modificarne la dichiarazione. Nella prossima lezione limiterà i parametri di tipo con i vincoli dei generics.

Gratis per iniziare

Impara Kotlin con un tutor IA — gratis

Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.

Corsi
51
Lezioni
203

Domande Frequenti

La lezione «Varianza use-site» è gratuita?

Sì — il testo completo di «Varianza use-site» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Kotlin Academy, passa a CoddyKit PRO. Il corso Kotlin Academy include 4 lezioni in totale.

Cosa imparerò in «Varianza use-site»?

Proiezioni di tipo Eserciti Kotlin Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Kotlin Academy?

Non è richiesta alcuna esperienza precedente. Kotlin Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «Varianza use-site»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Kotlin Academy?

Sì. Ogni lezione Kotlin Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Funzioni e classi generiche
  2. Varianza declaration-site
  3. Varianza use-site
  4. Vincoli dei generics
← Torna a Kotlin Academy