Immutable Data
immutable data란?
직역 : 변하지 않는 데이터.
만약에 값을 선언할 때
int cnt = 1;
cnt = 2;
이런식으로 값을 선언하고 2라는 값을 넣게 되면 0x02000000에 있던 값(예를 들어) 1에서 0x02000004에 있는 값 2로 대치 된 것이지 0x02000000에 있던 값이 변한게 아님(immutable data).
그에 반해서
List<int> cntArray = [1];
cntArray.add(2);
다음과 같이 할 때 cntArray[0]의 인덱스 주소는 고정이 되고 해당 주소의 값이 변경됨. 이러한 데이터를 mutable data라고 함.
즉, 값이 변경 > mutable
해당 주소의 값은 고정이 된 채 주소가 변경 > immutable
Dart에서 변수 할당 방식
var str = 'This is a String.'
str = 'This is another String.'
다음과 같은 변수를 선언하고 String을 할당했다고 칠 때, 'This is a String.'이라는 문자열 리터럴을 만들고 변수에는 해당 값의 위치에 대한 참조가 들어가 있음. 두 번째 줄에선 완전히 새로운 문자열을 만들고 첫 번째 문자열에 대한 참조를 두 번째 문자열에 대한 참조로 덮어쓰게 됨. 첫 번째 문자열은 해당 문자열에 대한 유효한 참조가 더 이상 없으면 도달할 수 없는 문자열로 표시되고 Dart의 garbage collector에 의해서 해당 문자열의 메모리가 해방됨.
garbage collector
메모리에 들어 있는 안쓰는 변수 등을 개발자가 다 해제 시켜주기 귀찮아서 이러한 일을 자동으로 해주는 것이 garbage collector임.
Immutable 해야하는 이유
- 리핵 : 함수가 동일한 Input에 대해서 동일한 Output을 보장하지 못하는 단점이 있다.
class Email {
String email = "Default";
String password = "Default";
}
위와 같은 class에 접근한다고 가정할 때 setPass("1243")를 호출하고 setEmail("abc@gmail.com")을 호출 했을 때 둘 다 비동기적인 함수이고 함수 시간이 오래 걸렸다고 가정할 때, setPass("1234")의 결과가
class Email {
String email = "Default";
String password = "1234";
}
가 아니라
class Email {
String email = "abc@gmail.com";
String password = "1234";
}
이 될수도 있다는 것을 말한다.
Side Effect : 어떤 객체를 접근해서 변화가 일어나는 행위를 말한다.
Dart Immutable Exam
final과 const
둘은 값을 한 번 지정하게 되면 바꿀 수 없다는 공통적인 속성을 가지고 있음.
final cnt = 1;
cnt = 2; // error
차이점
final은 선언시 값을 부여하지 않고 이후 최초 1번 값을 부여할 있음.
final은 이 파일이 실행될 때 해당하는 code의 위치에서 값이 결정되지만 const는 compile할 때에 값이 결정됨.(complie-time constants)
final list
list를 final로 선언하면 레퍼런스(참조)만 immutable이고 객체 내부는 mutable이라서 값을 변경하는 것은 가능함. 즉, 참조 값을 변경하는 경우에만 오류가 발생함.
void main() {
final List<int> a = [1,2,3];
a.add(4); // 됨
print(a);
a[0] = 5; // 됨
print(a);
a = [2,3,4]; // error 발생
}
내가 이해한 대로 정리를 해보자면 [1,2,3]이라는 리스트의 주소(참조 값)을 담고 있었는데 이를 다른 [2, 3, 4]라는 다른 리스트의 주소(참조 값)으로 변경해주게 되면 오류가 나는 것 같음.
class의 mutable한 속성
test gkgkgk
void main() {
User user1 = User(name: '지은', age: 30);
User user2 = user1;
user2.name = '용준'; // user2에서 이름을 바꿔도 참조하는 주소가 같기 때문에
print(user1.name); // 용준 출력
}
class User {
String? name;
int? age;
User({this.name, this.age});
}