Menu
Coddy logo textTech

Oggetti companion

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

Alcuni membri appartengono alla classe nel suo insieme anziché a una singola istanza. Kotlin li inserisce in un companion object all'interno della classe e li richiami tramite il nome della classe:

class Temperature(val celsius: Double) {
    companion object {
        fun fromFahrenheit(f: Double) = Temperature((f - 32) * 5 / 9)
    }
}

All'interno di main:

val boiling = Temperature.fromFahrenheit(212.0)
println(boiling.celsius)

Output:

100.0

fromFahrenheit è una funzione factory: una funzione che crea istanze. A differenza di un costruttore, ha un nome descrittivo e può restituire null invece di un oggetto. Con un private constructor, la factory è l’unico modo per accedere, quindi può prima controllare e ripulire l’input:

class Username private constructor(val text: String) {
    companion object {
        fun of(raw: String): Username? {
            val clean = raw.trim().lowercase()
            return if (clean.length in 3..12) Username(clean) else null
        }
    }
}

All’interno di main:

println(Username.of("  Ada_L ")?.text)
println(Username.of("x")?.text)
// Username("x")   // errore: il costruttore è privato

Output:

ada_l
null

L'oggetto companion appartiene alla classe, quindi può chiamare il costruttore privato, e il codice della classe usa i membri del companion senza prefisso. Qui ogni biglietto riceve il numero successivo da un unico contatore condiviso da tutti i biglietti:

class Ticket(val holder: String) {
    val number = nextNumber++

    companion object {
        private var nextNumber = 1
        val issued: Int
            get() = nextNumber - 1
    }
}

All'interno di main:

val a = Ticket("Ada")
val b = Ticket("Bo")
println("${a.holder} #${a.number}, ${b.holder} #${b.number}")
println("issued: ${Ticket.issued}")

Output:

Ada #1, Bo #2
issued: 2

Kotlin non ha la parola chiave static. I membri del companion svolgono quel ruolo: una sola copia per l'intera classe, accessibile come ClassName.member. Come qualsiasi oggetto, il companion viene creato una sola volta, quando la classe viene usata per la prima volta. Inserisci al suo interno ciò che non dipende da una singola istanza, come factory e contatori condivisi; tutto ciò che legge i dati di un'istanza resta un membro normale.

class User private constructor(val name: String) {
    fun greet() = "hi $name"             // richiede un'istanza: user.greet()

    companion object {
        fun guest() = User("guest")      // appartiene alla classe: User.guest()
    }
}
challenge icon

Sfida

Facile

Completa la classe Coupon. Il suo costruttore è privato, quindi i coupon vengono creati dalla factory Coupon.create(code, percent) nell’oggetto companion. Restituisce null a meno che il codice sia composto da 4 a 10 caratteri tra lettere maiuscole e cifre e la percentuale sia compresa tra 1 e 90. L’oggetto companion conta anche i coupon creati in created, che il codice esterno può leggere ma non modificare. apply(price) restituisce il prezzo meno lo sconto, arrotondato per difetto (price * (100 - percent) / 100).

Il codice fornito legge righe SAVE10 10 200 (codice, percentuale, prezzo). Stampa SAVE10: 180 oppure invalid coupon SAVE10 e infine created: seguito dal conteggio.

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

Provalo tu

fun main() {
    // Código de entrada/salida proporcionado: déjalo tal como está
    val input = generateSequence(::readLine).toList()
    for (line in input) {
        val (code, percent, price) = line.split(" ")
        val coupon = Coupon.create(code, percent.toInt())
        if (coupon == null) println("invalid coupon $code") else println("${coupon.code}: ${coupon.apply(price.toInt())}")
    }
    println("created: ${Coupon.created}")
}
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