Comparar objetos en Flutter con el paquete equatable
En este artículo, vamos a ver cómo funciona la igualdad en Flutter y Dart y como el paquete Equatable nos ayuda a tener un código más limpio sin necesidad de escribir tanto código repetitivo.
Ya sabemos que si queremos comparar dos variables podemos usar el operador ==
. Por ejemplo, si queremos comparar dos
cadenas de texto, el código es:
final car1 = "Toyota";
final car2 = "Toyota";
print(car1 == car2); // Resultado: true
Y si queremos comparar dos números, el código es:
final phone1 = 52123456;
final phone2 = 52123456;
print(phone1 == phone2); // Resultado: true
Veamos el resultado del código anterior en DartPad:
Comparar dos objetos de la misma clase
En los ejemplos anteriores vimos que es muy sencillo comparar dos variables usando ==
pero cuando queremos comparar
dos objetos de la misma clase ya no es tan sencillo.
Sí tenemos la siguiente clase:
class Car {
final String brand;
Car(this.brand);
}
Y creamos dos objetos:
final car1 = Car('Toyota');
final car2 = Car('Toyota');
print(car1 == car2); // false
A simple vista podemos decir que car1
y car2
son iguales, pero no es cierto. El resultado de
comparar car1
y car2
es false
Corramos el código anterior en DartPad:
¿Por qué pasa esto si todos sus valores son iguales? La respuesta es simple, en Dart por defecto el
operador ==
verifica la posición en memoria y no las propiedades de cada objeto. Y ya que car1
y car2
están en
posiciones de memoria diferente, el resultado de la comparación es false
.
Usando el constructor const
Utilizar el constructor const
le dice a Dart que solo debe crear una instancia de una clase para un conjunto de
valores dados en tiempo de compilación. Corramos el código anterior en DartPad pero esta vez utilizando
constructores const
:
Podemos ver que usar el constructor const
resuelve el problema al comparar dos objetos, pero, esto solo funciona
para objetos de los cuales conocemos su valor en tiempo de compilación. No hay forma de utilizar el
constructor const
en objetos creados en tiempo de ejecución. Es aquí donde entra el paquete Equatable
El paquete Equatable
Sin utilizar el paquete Equatable para comparar las propiedades de dos objetos y ver si son iguales tenemos que
sobreescribir ==
y hashCode
. El código de la clase Car
será:
class Car {
final String brand;
const Car(this.brand);
bool operator ==(Object other) =>
identical(this, other) ||
other is Car &&
runtimeType == other.runtimeType &&
brand == other.brand;
int get hashCode => brand.hashCode;
}
Equatable es un paquete que simplifica el proceso de comparar dos objetos de la misma clase sin
sobreescribir ==
y hashCode
.
Internamente, Equatable sobreescribe ==
y hashCode
para que nosotros no tengamos que perder tiempo
escribiendo código repetitivo.
Utilizando Equatable el código anterior será:
import 'package:equatable/equatable.dart';
class Car extends Equatable {
const Car(this.brand);
final String brand;
List<Object> get props => [brand];
}
Y si agregamos más propiedades como name
el código será:
class Car extends Equatable {
const Car(this.brand, this.name);
final String brand;
final String name;
List<Object> get props => [brand, name];
}
Corramos el código en DartPad para ver el resultado:
Podemos ver que el resultado es true
cuando los valores de las propiedades son los mismos. Intenta cambiando
los valores de car2
¿Cuál es el resultado?
Conclusión
El paquete Equatable es muy importante si queremos comparar dos objetos por el valor de sus propiedades, sin ßél tendríamos que escribir mucho código repetitivo.