불변 객체는 메모리에 할당한 뒤 값을 변경할 수 없는 객체입니다. String
, int
, double
, bool
, 그리고 const
로 선언된 객체 등이 불변 객체에 해당합니다. 불변 객체는 값이 변경되지 않기 때문에 동일한 값을 가진 객체를 여러 번 생성할 필요가 없으며, 동일한 메모리 주소를 재사용합니다.
String a = '철수';
a = '영희'; // '철수'를 변경한 게 아니라 '영희'를 생성(메모리 주소가 바뀜)
int b = 1;
b = 2; // 1을 변경한 게 아니라 2를 생성(메모리 주소가 바뀜)
가변 객체는 메모리에 할당된 뒤 값을 변경할 수 있는 객체입니다. List
, Set
, Map
, 커스텀 클래스 등이 가변 객체에 해당합니다. 가변 객체는 값이 계속 동일하다는 보장이 없기 때문에 재활용할 수 없고, 값이 같더라도 계속해서 새로운 메모리를 할당합니다.
List a = [];
a.add(1); // 메모리 주소를 유지하며 값을 변경
Set b = {};
b.add(1); // 메모리 주소를 유지하며 값을 변경
Map<String, dynamic> c = {};
c['name'] = '철수'; // 메모리 주소를 유지하며 값을 변경
객체를 비교하는 방법에는 두 가지가 있습니다:
Dart는 기본적으로 참조 비교를 사용합니다. 따라서 동일한 값을 가진 두 가변 객체는 다른 메모리 주소를 가지므로 false
를 반환합니다. 불변 객체는 동일한 값을 가지면 동일한 메모리 주소를 가지므로 참조 비교와 값 비교의 결과가 동일합니다.
값 비교를 구현하려면, Object
클래스의 비교 연산자(==
)와 hashCode
를 override하여 값을 기준으로 판단하도록 해야 합니다.
class A {
final int value;
const A(this.value);
bool operator ==(Object other) {
return identical(this, other) ||
other is A && runtimeType == other.runtimeType && value == other.value;
}
int get hashCode => value.hashCode;
String toString() {
return "A($value)";
}
}
void main() {
print(A(1) == A(1)); // true
print(A(1)); // A(1)
}
Equatable 패키지를 사용하면 위와 같은 번거로운 작업을 피할 수 있습니다. 불변 객체와 가변 객체에 대한 이해를 바탕으로, 객체 생성 및 비교의 효율성을 높일 수 있습니다. Equatable 패키지를 활용하면 값 비교를 더 쉽게 구현할 수 있으며, 이는 Flutter 애플리케이션 개발에서 중요한 역할을 합니다.