Sovrascrittura di hashCode e ==
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 71 di 110.
Per impostazione predefinita, due oggetti in Dart sono uguali solo se sono esattamente la stessa istanza in memoria. Ciò significa che due oggetti con valori identici sono comunque considerati diversi:
class Point {
int x, y;
Point(this.x, this.y);
}
void main() {
var p1 = Point(3, 4);
var p2 = Point(3, 4);
print(p1 == p2); // false - istanze diverse!
}Per confrontare gli oggetti in base ai loro valori, devi eseguire l'override sia dell'operatore == sia di hashCode. Questi due devono sempre essere sovrascritti insieme: se due oggetti sono uguali, devono avere lo stesso codice hash:
class Point {
final int x, y;
Point(this.x, this.y);
@override
bool operator ==(Object other) {
if (other is! Point) return false;
return x == other.x && y == other.y;
}
@override
int get hashCode => Object.hash(x, y);
}
void main() {
var p1 = Point(3, 4);
var p2 = Point(3, 4);
print(p1 == p2); // true - stessi valori!
}hashCode è fondamentale per le raccolte come Set e per le chiavi di Map. Il metodo di supporto Object.hash() di Dart combina più valori in un singolo codice hash. Senza un hashCode corretto, i tuoi oggetti non funzioneranno correttamente nelle raccolte basate su hash, anche se viene fatto l'override di ==.
Sfida
FacileCostruiamo un sistema di coordinate in cui i punti possano essere confrontati in base ai loro valori anziché ai loro indirizzi di memoria! Creerai una classe Coordinate che implementa correttamente l'uguaglianza basata sui valori, così da funzionare correttamente con i controlli di uguaglianza e con le raccolte basate su hash come Set.
Organizzerai il codice in due file:
coordinate.dart: crea una classeCoordinateche rappresenta un punto nello spazio 2D con i campifinal int xefinal int y. Esegui l'override sia dell'operatore==sia dihashCode, in modo che due coordinate con gli stessi valori di x e y siano considerate uguali. UsaObject.hash()per generare il codice hash a partire da entrambi i campi.main.dart: importa il tuo file delle coordinate e mostra come l'uguaglianza basata sui valori modifica il comportamento del confronto tra oggetti:- Crea due oggetti
Coordinatedistinti, entrambi con x:5e y:10 - Stampa se sono uguali usando
== - Stampa se sono identici (la stessa istanza) usando
identical() - Crea un
Set<Coordinate>e aggiungici entrambe le coordinate - Stampa la lunghezza dell'insieme (dovrebbe essere 1, dato che sono uguali!)
- Crea una terza coordinata con x:
3e y:7, e aggiungila all'insieme - Stampa la lunghezza finale dell'insieme
- Crea due oggetti
Questa sfida dimostra perché hashCode e == devono sempre essere sottoposti a override insieme. Set usa i codici hash per organizzare gli elementi, quindi senza un hashCode appropriato, anche gli oggetti uguali potrebbero essere memorizzati come duplicati!
Output previsto:
true
false
1
2Provalo tu
import 'coordinate.dart';
void main() {
// TODO: Crea dos objetos Coordinate distintos, ambos con x: 5 e y: 10
// TODO: Imprime si son iguales usando ==
// TODO: Imprime si son idénticos (la misma instancia) usando identical()
// TODO: Crea un Set<Coordinate> y agrega ambas coordenadas
// TODO: Imprime la longitud del conjunto (¡debería ser 1 porque son iguales!)
// TODO: Crea una tercera coordenada con x: 3 e y: 7 y agrégala al conjunto
// TODO: Imprime la longitud final del conjunto
}
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
1Fondamenti della programmazione orientata agli oggetti
File esterniLibrerie e importazioniIntroduzione alla programmazione orientata agli oggettiClassi e oggettiLa parola chiave thisMetodiVariabili di istanzaFondamenti dei costruttoriRiepilogo - Calcolatrice semplice4Sicurezza dei valori null
Introduzione alla sicurezza dei valori nullNullable e non nullableGli operatori ? e !La keyword late e la sicurezza dei valori nullOperatori null-awareSicurezza dei valori null nelle classiRiepilogo - Sistema di profili utente7Classi astratte e interfacce
Classi astratteMetodi astrattiInterfacce in DartInterfacce impliciteImplementare vs estendereInterfacce multipleRiepilogo - Calcolatore di forme10Collezioni e generici
Panoramica di List, Set e MapCollezioni sicure rispetto ai tipiClassi genericheMetodi genericiVincoli sui genericiIterable e IteratorRiepilogo - Archiviazione generica13Concetti avanzati di OOP
Composizione vs ereditarietàMetodi di estensioneClassi chiamabiliClassi sealed (Dart 3)Record (Dart 3)Pattern e matching (3.0)Enum con metodi16Progetto: Gestione della biblioteca
Panoramica del progettoClassi Libro e Utente2I costruttori in Dart
Costruttore predefinitoCostruttori con nomeListe di inizializzazioneCostruttori costantiCostruttori factoryCostruttori di reindirizzamentoRiepilogo - Crea forme5Incapsulamento
Membri pubblici e privatiConvenzione del prefisso _Visibilità a livello di libreriaApprofondimento su getter e setterNascondimento delle informazioniRiepilogo - Registri degli studenti8Mixin
Introduzione ai MixinCreare MixinUsare più MixinParola chiave on nei MixinMixin vs ereditarietàMixin vs interfacciaRiepilogo - Sistema animale11Metodi speciali
Sovrascrittura di toString()Sovrascrittura di hashCode e ==Interfaccia ComparableMetodo call()Sovrascrittura di noSuchMethodRiepilogo - Collezione personalizzata14Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneSingletonFactoryObserverStrategy3Proprietà delle classi
Membri di istanza e staticiCampi final e constVariabili lateMetodi e campi staticiGetter e setterRiepilogo - Gestore di conti bancari6Ereditarietà
Ereditarietà di baseLa parola chiave superOverride dei metodiL’annotazione @overrideLa parola chiave final per le classiCostruttori ed ereditarietàRiepilogo - Gerarchia dei dipendenti9Polimorfismo
Fondamenti di polimorfismoPolimorfismo tramite interfacceControllo del tipo a runtimeGli operatori is e asParola chiave covariantRiepilogo - Elaboratore di pagamenti12OOP asincrona
Future e async/awaitNozioni di base sugli streamController degli streamCostruttori asincroniAsync nei metodi di classeRiepilogo - Recupero dei dati15Pattern di progettazione Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositePattern RepositoryEsercitati da solo: Compilatore Dart online