일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- webrtc
- uint8array
- KakaoMap
- Babel standalone
- androidId
- swagger-typescript-api
- typescript
- Three-fiber
- Redux
- REST API
- jszip
- identifierForVender
- userevent_tracker
- Three js
- code editor
- Image Resize typescript
- web track
- Completer
- Prism.js
- react
- methodChannel
- FirebaseAnalytics
- uint16array
- Flutter
- Excel
- Raycasting
- Game js
- babel
- RouteObserver
- node
- Today
- Total
Never give up
Flutter - Call by reference 본문
먼저 call by value와 call by reference를 비교해보면
call by value는 말 그대로 값을 복사해서 저장합니다
call by reference는 값의 주소값을 저장합니다
그리고 필자는 List와 Map 같은 collection을 사용 할 때 값을 초기화 하는 부분에서
= 을 사용하면 call by value방식으로 저장될줄 알았었는데.. 아니었습니다
예를 들어
List<int> a = [0, 1 ,2];
List<int> b = a;
List<int> c = a;
print('a: $a\nb: $b\nc: $c');
c.clear();
print('a: $a\nb: $b\nc: $c');
해당 코드를 보면 c만 clear될 줄 알았는데 실제 찍힌 로그는
a: [0, 1, 2]
b: [0, 1, 2]
c: [0, 1, 2]
a: []
b: []
c: []
다음과 같습니다
메소드나 클래스를 사용하면 조금 다르지 않을까 해서 해봤는데..
메소드 실험
void main(){
List<int> a = [0, 1, 2];
test(a);
print('a : $a');
}
void test(List<int> list){
List<int> b = list;
print('b : $b');
b.clear();
print('b : $b');
}
로그
b : [0, 1, 2]
b : []
a : []
클래스 실험
void main(){
List<int> a = [0, 1, 2];
A aa = A(a);
aa.test();
print('a : $a');
}
class A{
final List<int> b;
A(this.b);
void test(){
print('b : $b');
b.clear();
print('b : $b');
}
}
로그
b : [0, 1, 2]
b : []
a : []
혹시나 해서 Map도 해봤는데 역시 동일했습니다
Map<int, String> a = {0 : 'a', 1 : 'b', 2 : 'c'};
Map<int, String> b = a;
Map<int, String> c = a;
print('a: $a\nb: $b\nc: $c');
c.clear();
print('a: $a\nb: $b\nc: $c');
로그
a: {0: a, 1: b, 2: c}
b: {0: a, 1: b, 2: c}
c: {0: a, 1: b, 2: c}
a: {}
b: {}
c: {}
여기서 추측해볼 수 있는건 collection을 초기화 시킬 때 저런식으로 사용하면
value가 아니라 reference가 복사됩니다
해당 코드에서는 [0, 1, 2]가 저장된 메모리 주소를 참조한다는 얘기가 되죠
이걸 방지하려면 다음과 같이 초기화를 하면 되는데
List<int> a = [0, 1 ,2];
List<int> b = [];
List<int> c = [];
b.addAll(a);
c.addAll(a);
print('a: $a\nb: $b\nc: $c');
c.clear();
print('a: $a\nb: $b\nc: $c');
혹은 다음과 같이 of를 사용하거나 또 다른 방법 등을 사용하시면 됩니다
List<int> a = [0, 1 ,2];
List<int> b = List.of(a);
List<int> c = List.of(a);
print('a: $a\nb: $b\nc: $c');
c.clear();
print('a: $a\nb: $b\nc: $c');
로그
a: [0, 1, 2]
b: [0, 1, 2]
c: [0, 1, 2]
a: [0, 1, 2]
b: [0, 1, 2]
c: []
그런데 좀 더 복잡한 데이터를 넘길때에는 생각을 조금 해봐야될거 같습니다
예를들면 Map<key, data> 여기서 data 안에 collection이 들어가는 경우죠
현재 필자가 개발중인 앱의 data type은 다음과 같은데
List<String> a;
Uint8List b;
String c, d, e, f;
Map<String, int> g = {};
DateTime h;
List<data> i;
//data = String 2, DateTime 1
Map에서 값을 저장하는것까지는 완료가 되는데 다른 화면에 전달해서 출력을 해보니
i값은 제대로 출력되지만 a값은 제대로 출력이 안됐습니다
각각 값 저장방식은
a
void method1() {
a.add(value);
notifyListeners();
}
void method2(){
map[key] = data(value); //value안에 a값이 들어갑니다
notifyListeners();
initData(); //<= 잡았다 요놈!
}
i
@override
void method2() {
if (null 체크) {
map[key].i.add(value);
notifyListeners();
}
}
이걸 해결하기 위해 정말 나쁜짓(?)을 했습니다 a를 String으로 변환해서 처리해버린거죠..
즉 jsonEncode(List)를 사용해서 String값으로 저장하고 jsonDecode(String)로 List형태로 출력을 했었는데
dart의 collection에 저장 방식이 call by reference라는것을 알았다면 이런 삽질은 안했을것입니다...
(닉네임을 삽질하는 개발자로 바꿔야되나 심각하게 고민중입니다..)
'해왔던 삽질..' 카테고리의 다른 글
Flutter - Locale data has not been initialized (5) | 2021.01.18 |
---|---|
Flutter - Looking up a deactivated widget's ancestor is unsafe. (0) | 2020.12.26 |
Flutter - Loading hud (0) | 2020.12.12 |
첫번째 앱 등록 후기 (4) | 2020.09.16 |
Flutter - abstract class extends vs implements (0) | 2020.08.17 |