Dart 복사하기 (..) cascade 연산자

SEUNGHWANLEE·2022년 8월 23일
0

Flutter

목록 보기
6/6
post-thumbnail

어떤 데이터를 주고 받을 때 클래스를 생성해서 다루는 일은 빈번하게 이루어진다. 하지만 잘못사용하게 된다면 데이터의 누락 또는 잘못된 사용으로 값이 변조될 수 있다.

Dart 에서 사용되는 cascade operator 및 활용 가능한 데이터 모델 클래스에 대해 다뤄보고자 한다.

예를 들어 병이란 데이터는 이름과 용량이란 값을 가지고 있다고 가정해보자. 그럼 아래와 같이 클래스를 작성할 수 있다.

class Bottle {
	String? name;
    final int capacity;
}

용량은 병이 한번 제조된 후 변경될 수 없을 거라 생각해 final로 선언해주었다.

이와 같은 상황을 가정해 새로운 인스턴스를 생성할 수 있는 메소드를 추가해보자!

  • 이름으로부터 새로운 병을 만들어야 하는 경우
  • 이름을 수정해서 새로운 병을 만들어야 하는 경우

위 2개의 기능을 충족시켜줄 수 있는 메소드를 추가해보면 아래와 같이 작성할 수 있다.

factory Bottle.from(String name) => Bottle(
        capacity: 10,
        name: name,
      );

Bottle addName(String updatedName) => Bottle(
        capacity: capacity,
        name: updatedName,
      );

factory 패턴을 사용해서 기본 용량 10을 가진 새로운 병을 생성하는 메소드와 이미 있는 병에서 이름만 수정해서 새로운 병을 생성해주는 메소드를 작성했다. 이제 이 2개를 활용해보자.

더 정확한 인스턴스의 상태를 알 수 있도록 간단하게 print 해볼 수 있는 메소드도 추가해보았는데 완성된 클래스는 아래와 같다.

class Bottle {
  String? name;
  final int capacity;

  Bottle({
    required this.capacity,
    this.name,
  });

  factory Bottle.from(String name) => Bottle(
        capacity: 10,
        name: name,
      );

  Bottle addName(String updatedName) => Bottle(
        capacity: capacity,
        name: updatedName,
      );

  void printInfo() => print(
        'hashCode: $hashCode, capacity: $capacity, name: $name',
      );
}

위 함수를 통해서 총 6가지의 경우를 테스트 해보려 한다.

  1. 새로운 인스턴스 생성
  2. cascade 연산자를 활용한 인스턴스 생성
  3. cascade 연산자를 활용해 기존 인스턴스 복사
  4. 기존 값 복사와 동시에 새로운 인스턴스 생성
  5. cascade 연산자 및 새로운 인스턴스 생성 메소드 활용
  6. factory 패턴 활용

테스트 해볼 코드는 아래와 같다.

void main() {
  /// 1. create new instance
  Bottle water = Bottle(capacity: 10);
  water.printInfo();

  /// 2. using cascade operator
  Bottle icis = Bottle(capacity: 12)..name = 'icis';
  icis.printInfo();

  /// 3. using same instance of `icis` and change name to [evian]
  Bottle evian = icis..name = 'evian';
  evian.printInfo();

  /// 4. copy value and create new instance
  Bottle icis2 = icis.addName('second icis');
  icis2.printInfo();

  /// 5. copy instance
  Bottle icis3 = icis..addName('third icis');
  icis3.printInfo();

  /// 6. create new instance
  Bottle samdasu = Bottle.from('samdasu');
  samdasu.printInfo();
}

그리고 결과는 다음과 같다.

hashCode: 490920693, capacity: 10, name: null
hashCode: 978607171, capacity: 12, name: icis
hashCode: 978607171, capacity: 12, name: evian
hashCode: 1050812338, capacity: 12, name: second icis
hashCode: 978607171, capacity: 12, name: evian
hashCode: 761191122, capacity: 10, name: samdasu

여기서 3번 같은 경우 icis 의 인스턴스를 복사해 이름을 수정해주었지만 icis의 이름 또한 evian으로 변경되었다.

그 이유는 Shallow Copy 가 일어났기 때문이다. 같은 메모리 주소를 참조하고 있으며 icis의 인스턴스를 복사해 name의 값을 변경해주었다.

그렇다면 5번과 같은 경우에는 왜 namethird icis로 변경되지 않았을까?

4번 같은 경우에는 addName( ) 메소드가 새로운 인스턴스를 반환한다.

icis..

과정에서 기존 icis의 인스턴스가 반환된다.

icis..addName(_)

하지만 여기서 addName을 통해서 새로운 인스턴스가 반환이 되는데, 이미 icis의 인스턴스가 반환된 상태이므로 icis3에 할당되는 인스턴스는 icis 인스턴스이다.

마무리

만약 데이터 클래스 내에 콜백 함수나 수정될 수 있는 데이터가 있어 cascade(..) 연산자를 통해 수정을 한다면 5번과 같은 경우를 주의해서 사용해야한다.

profile
잡동사니 😁

0개의 댓글