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.0fromFahrenheit è 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 è privatoOutput:
ada_l
nullL'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: 2Kotlin 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()
}
}Sfida
FacileCompleta 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}")
}
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
1Classi e oggetti
Lavorare con i fileDefinire le classiCostruttori primariBlocchi init e convalidaCostruttori secondariRiepilogo - Tessera della biblioteca4Ereditarietà
Classi aperte e sottoclassiRidefinizione dei membrisuper e costruttoriClassi astratteRiepilogo - Elenco del personale2Proprietà e incapsulamento
Accessor personalizzatiModificatori di visibilitàSetter privatilazy e lateinitRipasso - Conto bancario5Interfacce
Dichiarare le interfacceMetodi predefinitiInterfacce multipleLe interfacce come tipiRiepilogo - Metodi di pagamento8Tipi generici
Funzioni genericheClassi genericheVincoli sui tipiVarianza con in e outRiepilogo - Coda con priorità11Progetto: Gestione della biblioteca
Libri e sociPrendere in prestito i libri3Oggetti e companion
Dichiarazioni di oggettiOggetti companionCostanti con constEspressioni oggettoRipasso - BiglietteriaEsercitati da solo: Playground Kotlin