Menu
Coddy logo textTech

Classi generiche

Fa parte della sezione Programmazione orientata agli oggetti del percorso Kotlin di Coddy. Lezione 38 di 57.

Anche una classe può avere parametri di tipo. Box<T> contiene un valore di qualsiasi tipo e ogni istanza fissa il tipo: un Box<Int> accetta solo valori Int:

class Box<T>(var value: T) {
    fun describe() = "box with $value"
}

All'interno di main:

val numberBox = Box(42)
val textBox = Box("hello")
numberBox.value += 1
println(numberBox.describe())
println(textBox.describe())
// numberBox.value = "x"   // error: un String no es un Int

Output:

box with 43
box with hello

I contenitori sono le classi generiche più comuni. Un'implementazione di Stack<T> funziona per ogni tipo di elemento e il compilatore controlla cosa viene inserito e cosa restituito:

class Stack<T> {
    private val items = mutableListOf<T>()
    val size: Int
        get() = items.size

    fun push(item: T) { items.add(item) }
    fun pop(): T? = items.removeLastOrNull()
    fun peek(): T? = items.lastOrNull()
}

All'interno di main:

val stack = Stack<String>()
stack.push("a")
stack.push("b")
println(stack.pop())
println(stack.peek())
println(stack.size)

Output:

b
a
1

L'argomento di tipo viene dedotto dagli argomenti del costruttore, se presenti, come in Box(42). Altrimenti, specificalo: Stack<String>(). Le istanze con argomenti di tipo diversi sono tipi diversi, quindi una Stack<String> non viene mai confusa con una Stack<Int>. Anche le funzioni di una classe generica possono aggiungere parametri di tipo propri:

class Box<T>(val value: T) {
    fun <R> map(f: (T) -> R): Box<R> = Box(f(value))
}

All'interno di main:

val length = Box("kotlin").map { it.length }
println(length.value + 1)

Output:

7

Le interfacce generiche seguono le stesse regole. Una classe può implementarne una in modo generico oppure per un particolare argomento di tipo:

interface Repository<T> {
    fun add(item: T)
    fun all(): List<T>
}
class MemoryRepository<T> : Repository<T> {
    private val items = mutableListOf<T>()
    override fun add(item: T) { items.add(item) }
    override fun all() = items.toList()
}
class TagRepository : Repository<String> {
    private val tags = sortedSetOf<String>()
    override fun add(item: String) { tags.add(item.lowercase()) }
    override fun all() = tags.toList()
}

Dentro main:

val ids = MemoryRepository<Int>()
ids.add(3); ids.add(1)
val tags = TagRepository()
tags.add("Kotlin"); tags.add("JVM")
println("${ids.all()} ${tags.all()}")

Output:

[3, 1] [jvm, kotlin]
challenge icon

Sfida

Facile

Scrivi la classe generica History<T>(limit) che memorizza gli ultimi limit elementi. add(item) aggiunge un elemento e rimuove il più vecchio quando ce ne sono più di limit. latest è l'elemento più recente oppure null, e all() restituisce gli elementi dal più vecchio al più recente come lista di sola lettura. Poi scrivi l'estensione History<Int>.average(), che esiste solo per gli archivi di numeri e restituisce la media intera dei numeri conservati (0 se è vuoto).

Il codice fornito legge il limite, una riga di parole e una riga di numeri. Riempie un History<String> e un History<Int> e stampa le parole conservate, la parola più recente, i numeri conservati, la loro media e empty latest: null.

Il tuo codice va in History.kt. Main.kt contiene il codice di input/output fornito e non può essere modificato.

Provalo tu

fun main() {
    // Codice di input/output fornito: lascialo così com'è
    val input = generateSequence(::readLine).toList()
    val limit = input[0].toInt()
    val words = History<String>(limit)
    for (w in input[1].split(" ")) words.add(w)
    val numbers = History<Int>(limit)
    for (n in input[2].split(" ")) numbers.add(n.toInt())
    println("words: ${words.all()}")
    println("latest word: ${words.latest}")
    println("numbers: ${numbers.all()}")
    println("average: ${numbers.average()}")
    println("empty latest: ${History<Char>(3).latest}")
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Playground Kotlin