const란 간단히 말해 컴파일 시점에 값을 알고 있는 것이다. 값은 변하지 않고 const로 선언된 객체는 런타임 중에 캐시되어 동일한 객체를 여러 번 참조할 때 메모리를 더 효율적으로 사용할 수 있다.
여기서 헷갈릴 수 있는 것은 final도 변하지 않는 값이지만, 차이점이 있다면
final은 런타임에 값을 결정한다. 그래서 DateTime.now()은 실행 시점에만 가져올 수 있는 값이기 때문에 final에만 사용할 수 있는 것!
클래스의 모든 멤버 변수가 final로 정의되어 있어야 한다.
아래와 같은 클래스가 있다.
class Food {
final String name;
final int price;
const Food({required this.name,required this.price});
}
그리고 변수 값이 똑같은 두 개의 인스턴스를 만든다.
final ham = Food(name:"hamburger", price:5900);
final ham2 = Food(name:"hamburger", price:5900);
print(ham == ham2) 결과는 false 이다.
그 이유는, 클래스 내부의 값들이 일치해도, 두 인스턴스가 각각 생성되었기 때문에 서로 다른 인스턴스라고 여기기 때문이다.
이번에는 인스턴스를 생성할때 한쪽에만 const를 붙여본다.
final ham = Food(name:"hamburger", price:5900);
final ham2 = const Food(name:"hamburger", price:5900);
여전히 print(ham == ham2) 결과는 false 이다.
이번에는 두 곳 모두에 const를 붙여본다.
final ham = const Food(name:"hamburger", price:5900);
final ham2 = const Food(name:"hamburger", price:5900);
print(ham == ham2) 결과는 true 이다.
이번에는 두 인스턴스가 같은 인스턴스라고 인식했다. 이미 컴파일 시점에 같은 값으로 초기화되었기 때문이다.
또 다른 예시를 보자
class Person {
final String name;
final int age;
const Person(this.name, this.age);
}
void main() {
const person1 = const Person('John', 30);
const person2 = const Person('John', 30);
final person3 = Person('John', 30);
print(identical(person1, person2)); // true
print(identical(person1, person3)); // false
}
위 코드에서는 Person 클래스를 정의하고, const 생성자를 사용하여 person1과 person2를 선언한다. 그리고 일반 생성자를 사용하여 person3을 선언한다.
identical(person1, person2)이 true인 이유는 person1과 person2는 모두 const 생성자를 사용하여 선언되었으며, 같은 값으로 초기화되었기 때문에 같은 객체로 취급된다.
반면, person3은 일반 생성자를 사용하여 선언되었고 메모리에서 person1과 다른 위치에 할당되었기 때문에 identical(person1, person3)은 false가 된다.
그냥 간단히 말해서 identical(1,1)은 당연히 true다. 객체를 const로 생성하면 저런 숫자같은 상수가 된다는 뜻!
identical 함수는 주어진 두 객체가 동일한 객체인지를 비교하는 메서드이다. 즉, 메모리에서 같은 위치에 있는 객체인지를 확인한다.
var o = new Object();
var isIdentical = identical(o, new Object()); // false, different objects.
isIdentical = identical(o, o); // true, same object
isIdentical = identical(const Object(), const Object()); // true, const canonicalizes
isIdentical = identical([1], [1]); // false
isIdentical = identical(const [1], const [1]); // true
isIdentical = identical(const [1], const [2]); // false
isIdentical = identical(2, 1 + 1); // true, integers canonicalizes
const 키워드를 사용한 경우, 컴파일 시점에 이미 해당 인스턴스가 생성되어 있음이 보장된다. 따라서 const 키워드를 사용하여 생성한 객체는 모두 컴파일 시점에 할당된 상수 메모리에 저장됩니다. 이때 같은 값으로 초기화된 const 객체들은 같은 메모리 공간을 참조하게 되어 리소스 낭비를 방지할 수 있게 된다.
const에 알기도 하고 자주 썼지만 이렇게 클래스와 객체로 비교했을 때로 보니 또 생소해보였다. 재밌당 앞으로 const를 제대로 알고 쓰장