[Flutter] freezed로 만들어진 여러타입의 모델을 하나의 타입으로 감싸는 방법

Raon·2023년 5월 18일
0

Flutter

목록 보기
17/24

freezed를 사용할 때, 보통 아래와 같은 방식을 사용해 데이터 모델을 생성한다.

import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter/foundation.dart';

part 'your_model_name.freezed.dart';
part 'your_model_name.g.dart';


class Animal with _$Animal {
  const factory Animal({
    required String name,
    ("") String type,
  }) = _MyModel;

  factory Animal.fromJson(Map<String, Object?> json)
      => _$AnimalFromJson(json);
}

이 모델을 사용을 사용할 때 아래와 같이 사용할 수 있다.

final Animal dog = Animal(name: "개", type: "포유류");
final Animal bird = Animal(name: "앵무새", type: "조류");
final Animal shark = Animal(name: "상어", type: "어류");

예시에 있는 모델과 같이 name, type같은 간단한 데이터를 저장하는 모델인 경우 이렇게 사용해도 문제가 없지만, 아래와 같은 조건이 붙으면 어떻게 해결해야할까?

  • type변수를 제거한다.
  • 포유류 데이터는 이빨의 수를 변수로 가지고 있어야한다.(이빨이 없는 경우 0으로 간주한다)
  • 조류 데이터는 날개의 길이를 변수로 가지고 있어야한다.(날개가 없는 경우 0으로 간주한다)
  • 어류 데이터는 등지느러미의 길이를 변수로 가지고 있어야한다.(등지느러미가 없는 경우 0으로 간주한다.)

이 경우, 위의 조건을 만족시키기 위해서는 Animal 내부에 이빨의 수를 나타내는 toothCount, 날개의 길이를 나타내는 wingLength, 등지느러미의 길이를 나타내는 finLength를 모두 변수로 가지고 있어야한다. 하지만 type변수를 제거해야하므로 어떤 동물이 어떤 종인지 구분할 수 없게 된다.

따라서 이런 경우 freezed를 사용할때 어떻게 해결해야 할까? 아래의 코드에 그 해답이 나와있다.

import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter/foundation.dart';

part 'your_model_name.freezed.dart';
part 'your_model_name.g.dart';


class Animal with _$Animal {
  const factory Animal.mammal({
    required String name,
    (0) int toothCount,
  }) = _Mammal;
  
  const factory Animal.fish({
    required String name,
    (0.0) double finLength,
  }) = _Fish;
  
  const factory Animal.bird({
    required String name,
    (0.0) double wingLength,
  }) = _Bird;

  factory Animal.fromJson(Map<String, Object?> json)
      => _$AnimalFromJson(json);
}

이렇게 작성하게 될 경우 선언은 아래와 같이 할 수 있다.

final Animal dog = Animal.mammal(name: "개", toothCount: 28);
final Animal shark = Animal.fish(name: "상어", finLength: 29.5);
final Animal parrot = Animal.bird(name: "앵무새", wingLength: 37.4);

위의 코드와 같이 선언할 경우 dog, parrot, shark에 Animal객체가 선언될 때 내부적으로

  • Animal.mammal = _Mammal
  • Animal.bird = _Bird
  • Animal.fish = _Fish

와 같이 private로 선언되어 있는 클래스로 생성된다.

잘 이해가 안된다면 freezed로 생성된 your_model.freezed.dart파일을 열어보면 알 수 있는데, 요점은 아래와 같다.

freezed로 생성된 .freezed.dart파일에는 Animal객체가 abstract로 선언되어 있다.
_Mammal, _Fish, _Bird객체는 보통의 class로 선언되며 이 때 추상 클래스로 선언된 Animal을 상속받아 private클래스로 작성된다.

결국 앞서 작성되어 있던 factory키워드로 작성된 클래스 생성 로직의 가장 뒤에 =_Model과 같은 형식으로 작성된 부분이 있기에, freezed로 생성된 모델을 불러올 수 있는 것이다.

만약 _키워드를 제거한다면 타입을 직접 선언할 수 있겠지만, freezed는 is, as와 같은 직접적으로 타입을 작성하는 방식보다는 freezed에서 제공되는 when, map등의 함수를 이용하는 것을 권장하고 있다.

이렇게 freezed를 사용해서 다양한 데이터를 하나의 타입으로 선언할 수 있는 방법에 대해 알아보았다.

freezed를 만일 사용하지 않는다면 상속을 통해 구현될 수 있지만 freezed는 공식적으로 상속을 지양하기 때문에 이러한 방법이 나온 것 같다.

profile
Flutter 개발자

0개의 댓글