equals, hashCode, toString
Parte da seção Programação Orientada a Objetos do Journey de Kotlin da Coddy. Lição 35 de 57.
Toda classe herda toString(), equals() e hashCode() de Any. As versões herdadas operam com base na identidade: toString() fornece o nome da classe e um código hash, e equals() é true somente para o mesmo objeto. Sobrescrever toString() fornece aos objetos um texto legível, usado por println e por templates de string:
class Money(val cents: Int) {
override fun toString() = "$%d.%02d".format(cents / 100, cents % 100)
}Dentro de main:
val price = Money(1250)
println(price)
println("total: ${Money(99)}")Saída:
$12.50
total: $0.99== chama equals(), enquanto === verifica se duas referências apontam para o mesmo objeto. Para comparar por valor, substitua equals. Seu parâmetro é Any?, portanto ele verifica o tipo primeiro e depois compara as propriedades relevantes:
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()
}Dentro de main:
val a = Isbn("978-0-441-17271-9")
val b = Isbn("9780441172719")
println(a == b)
println(a === b)Saída:
true
falseObjetos iguais devem ter códigos hash iguais. HashSet e HashMap encontram entradas primeiro por meio de hashCode() e só depois chamam equals(), portanto sobrescrever equals sem hashCode faz com que objetos iguais pareçam diferentes neles. Sempre sobrescreva ambos, calculados a partir das mesmas propriedades:
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"
}Dentro de 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)Saída:
2
trueUma classe de dados gera os três a partir das propriedades do seu construtor. Escreva-os você mesmo quando a igualdade deve usar menos propriedades ou uma forma normalizada, como um endereço de e-mail que ignora maiúsculas e minúsculas:
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>"
}Dentro de main:
val users = listOf(User("Ada@Example.com", "Ada"), User("ada@example.com ", "A. Lovelace"))
println(users.distinct())Saída:
[Ada <ada@example.com>]Desafio
FácilDois produtos são iguais quando seus sku coincidem, independentemente do que os outros campos informem. Substitua equals() e hashCode() em Product para considerar apenas sku, e toString() para que um produto seja impresso como A1 tea 450. Em seguida, complete mergeCatalog(products), que mantém a primeira ocorrência de cada produto na ordem original.
O código fornecido lê produtos como linhas no formato sku,name,price e uma última linha com um sku a ser pesquisado. Ele imprime cada produto mantido, removed: 2 e A1 in catalog: true, pesquisando o sku em um HashSet.
Seu código deve ser inserido em Product.kt e Functions.kt. Main.kt contém o código fornecido de entrada/saída e não pode ser editado.
Experimente você mesmo
fun main() {
// Código de entrada/saída fornecido: mantenha-o como está
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()}")
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Classes e Objetos
Trabalhando com ArquivosDefinindo ClassesConstrutores PrimáriosBlocos init e ValidaçãoConstrutores SecundáriosRecapitulação - Cartão da Biblioteca4Herança
Classes Abertas e SubclassesSobrescrevendo Membrossuper e ConstrutoresClasses AbstratasRevisão - Diretório de Funcionários7Classes Especiais
Classes de DadosClasses EnumHierarquias Seladasequals, hashCode, toStringRecapitulação - Rastreador de Pedidos2Propriedades e Encapsulamento
Acessores PersonalizadosModificadores de VisibilidadeSetters Privadoslazy e lateinitRevisão - Conta Bancária5Interfaces
Declarando InterfacesMétodos PadrãoMúltiplas InterfacesInterfaces como TiposRecapitulação - Métodos de Pagamento8Genéricos
Funções genéricasClasses genéricasRestrições de tipoVariância com in e outRecapitulação - Fila de prioridade11Projeto: Gerenciamento de Biblioteca
Livros e MembrosEmpréstimo de LivrosPratique por conta própria: Playground de Kotlin