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객체가 선언될 때 내부적으로
와 같이 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는 공식적으로 상속을 지양하기 때문에 이러한 방법이 나온 것 같다.