🐻‍❄️

Freezed を利用してデータクラスを作成する

2021/11/24に公開

Freezed とは

Freezed はDart言語でデータクラスの生成をサポートしてくれるライブラリです。

  • コンストラクタを記述するとプロパティも自動的に定義してくれる
  • オブジェクトのすべてのプロパティをそれぞれ比較/表示できるようにする(== , toString)
  • 異なる値を持つオブジェクトを複製できるようにする(CopyWith)
  • オブジェクトのシリアライズ・デシリアライズできるようにする (ToJson, FromJson)

その他に Union や Sealed Class のサポートをしているらしいです。
詳しくは公式ドキュメントに記載があるので確認してください。

環境

本記事は以下の環境で動作確認をしています。

  • OS : macOS Monterey 12.0.1
  • Dart : v2.5.3
  • IDE : VS Code

セットアップ

Build Runner

Freezed では Build Runner というライブラリを利用してコードを生成します。VS Code で簡単に Build Runner を動作させられるように拡張機能をインストールしておきます。

Image.png

Freezed

Freezed を利用してデータクラスを作成するときには Freezed 記法でクラスを記述する必要があります。VS Code ではこれらの記述をしたクラスを自動生成してくれる拡張機能が用意されているのでインストールする。

Image.png

InetelliJ や Android Studio の場合は Freezed 用の Live Templates が用意されているらしいです。IntelliJ やAndroid Studio を利用している場合はこちらをインストールすると良さそうです。

依存関係を追加する

Freezed を使うには pubspec.yaml に以下の依存関係を追加する。

name: sample
description: A simple command-line application.
version: 1.0.0
# homepage: https://www.example.com

environment:
  sdk: '>=2.14.4 <3.0.0'


dependencies:
  freezed_annotation: ^1.0.0 # これを追加する
  json_serializable: ^6.0.1 # 必要であれば追加する

dev_dependencies:
  lints: ^1.0.0
  build_runner: ^2.1.5 # これを追加する
  freezed: ^1.0.0 # これを追加する

データクラスを作成する

データクラスの雛形の作成

コマンドパレットで 「Freezed: Generate a new Freezed class」 というメニューを選択する。

Image.png

次に作成したいクラス名を入力する。
今回は 「Animal」 という名称のクラスを作成してみる。

Image.png

次にtoJsonとfromJsonをサポートするか決める。
今回は「No」にしてtoJsonとfromJsonをサポートしないようにしてみます。

Image.png

そして最後にファイルの出力先を決める。
今回は Dart プロジェクトの bin フォルダに出力するようにしてみる。
(エラーダイアログがでることがありますが特に問題はないありません)

Image.png

データクラスの雛形を編集する

bin フォルダには以下の内容の Animal クラスが生成される。
この時点ではエラーが発生していますが後々解消できるので問題ないです。

import 'package:freezed_annotation/freezed_annotation.dart';

part 'animal.freezed.dart';
part 'animal.g.dart';


class Animal with _$Animal {
  factory Animal() = _Animal;
	
  factory Animal.fromJson(Map<String, dynamic> json) =>
			_$AnimalFromJson(json);
}

このAnimal クラスに必要なプロパティを定義していく。
今回はAnimalクラスに nameage を追加してみる。

import 'package:freezed_annotation/freezed_annotation.dart';

part 'animal.freezed.dart';
part 'animal.g.dart';


class Animal with _$Animal {
  factory Animal({String? name, int? age}) = _Animal;
}

そしてコマンドパレットで Build Runner: Build メニューを選択する。
すると animal.freezed.dart が生成されます、これでデータクラスの作成は完了です。

Image.png

動作確認

今回はtoJsonfromJson の実装は省きましたので以下の3つの機能が使えます。

  • コンストラクタを記述するとプロパティも自動的に定義してくれる
  • オブジェクトのすべてのプロパティをそれぞれ比較/表示できるようにする(== , toString)
  • 異なる値を持つオブジェクトを複製できるようにする(CopyWith)

実際に生成したAnimal クラスを以下のコードで動作確認してみます。
出力結果を見てわかるように各機能が問題なく動作していました。

サンプルコード

void main(List<String> arguments) {
  var yagi = Animal(name: "Yagi", age: 0);
  print("■ PROPERTY AND TOSTRING");
  print("name ${yagi.name}");
  print("age  ${yagi.age}");
  print("toString $yagi");

  var ushi = Animal(name: "Ushi", age: 0);
  var clone = yagi.copyWith();
  print("■ COMPARE");
  print("== ${yagi == ushi}");
  print("== ${yagi == clone}");

  var renameYagi = yagi.copyWith(name: "ああああ");
  var oldYagi = yagi.copyWith(age: 100);
  print("■ COPY WITH");
  print("toString $renameYagi");
  print("toString $oldYagi");
}

出力結果

■ PROPERTY AND TOSTRING
name Yagi
age  0
toString Animal(name: Yagi, age: 0)
■ COMPARE
== false
== true
■ COPY WITH
toString Animal(name: ああああ, age: 0)
toString Animal(name: Yagi, age: 100)

参考文献

Discussion