equals, hashCode, toString
Fa parte della sezione Programmazione orientata agli oggetti del percorso Kotlin di Coddy. Lezione 35 di 57.
Ogni classe eredita toString(), equals() e hashCode() da Any. Le versioni ereditate operano sull’identità: toString() restituisce il nome della classe e un codice hash, mentre equals() è true solo per lo stesso oggetto. Sovrascrivendo toString() si assegna agli oggetti un testo leggibile, usato da println e dai template di stringa:
class Money(val cents: Int) {
override fun toString() = "$%d.%02d".format(cents / 100, cents % 100)
}All’interno di main:
val price = Money(1250)
println(price)
println("total: ${Money(99)}")Output:
$12.50
total: $0.99== chiama equals(), mentre === verifica se due riferimenti puntano allo stesso oggetto. Per confrontare i valori, esegui l'override di equals. Il suo parametro è Any?, quindi verifica prima il tipo e poi confronta le proprietà pertinenti:
class Isbn(code: String) {
val digits = code.filter { it.isDigit() }
override fun equals(other: Any?) = other is Isbn && other.digits == digits
override fun hashCode() = digits.hashCode()
}All'interno di main:
val a = Isbn("978-0-441-17271-9")
val b = Isbn("9780441172719")
println(a == b)
println(a === b)Output:
true
falseGli oggetti uguali devono avere codici hash uguali. HashSet e HashMap cercano le voci prima tramite hashCode() e solo dopo chiamano equals(), quindi sovrascrivere equals senza hashCode fa sì che gli oggetti uguali sembrino diversi al loro interno. Sovrascrivi sempre entrambi, calcolandoli a partire dalle stesse proprietà:
class Isbn(code: String) {
val digits = code.filter { it.isDigit() }
override fun equals(other: Any?) = other is Isbn && other.digits == digits
override fun hashCode() = digits.hashCode()
override fun toString() = "ISBN $digits"
}All'interno di main:
val shelf = hashSetOf(Isbn("978-0-441-17271-9"), Isbn("9780441172719"), Isbn("0-14-143951-3"))
println(shelf.size)
println(Isbn("9780441172719") in shelf)Output:
2
trueUna data class genera tutti e tre a partire dalle sue proprietà del costruttore. Scrivili tu quando l’uguaglianza dovrebbe usare meno proprietà o una forma normalizzata, come un indirizzo email che ignora le maiuscole e le minuscole:
class User(val email: String, val name: String) {
private val key = email.trim().lowercase()
override fun equals(other: Any?) = other is User && other.key == key
override fun hashCode() = key.hashCode()
override fun toString() = "$name <$key>"
}All’interno di main:
val users = listOf(User("Ada@Example.com", "Ada"), User("ada@example.com ", "A. Lovelace"))
println(users.distinct())Output:
[Ada <ada@example.com>]Sfida
FacileDue prodotti sono uguali quando il loro sku corrisponde, indipendentemente da ciò che indicano gli altri campi. Sovrascrivi equals() e hashCode() in Product basandoti solo su sku, e toString() in modo che un prodotto venga stampato come A1 tea 450. Poi completa mergeCatalog(products), che mantiene la prima occorrenza di ogni prodotto nell'ordine originale.
Il codice fornito legge i prodotti da righe nel formato sku,name,price e una riga finale con uno sku da cercare. Stampa ogni prodotto mantenuto, removed: 2 e A1 in catalog: true, cercando lo sku in un HashSet.
Il tuo codice va in Product.kt e Functions.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 products = input.dropLast(1).map { line ->
val (sku, name, price) = line.split(",")
Product(sku, name, price.toInt())
}
val kept = mergeCatalog(products)
for (p in kept) println(p)
println("removed: ${products.size - kept.size}")
val probe = Product(input.last(), "?", 0)
println("${input.last()} in catalog: ${probe in kept.toHashSet()}")
}
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 personale7Classi speciali
Classi di datiClassi enumGerarchie sigillateequals, hashCode, toStringRiepilogo - Monitoraggio ordini2Proprietà 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 libriEsercitati da solo: Playground Kotlin