やりたいこと
以下のような freezed な User モデルがある
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
part 'user.g.dart';
@freezed
class UserModel with _$UserModel {
factory UserModel({
required String lastName,
required String firstName,
}) = _UserModel;
factory UserModel.fromJson(Map<String, dynamic> json) =>
_$UserModelFromJson(json);
}
このUserモデルに fullName
という getter を定義したい
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
part 'user.g.dart';
@freezed
class UserModel with _$UserModel {
factory UserModel({
required String lastName,
required String firstName,
}) = _UserModel;
factory UserModel.fromJson(Map<String, dynamic> json) =>
_$UserModelFromJson(json);
String get fullName => '$lastName $firstName'; /////////// これ ////////////
}
エラー
freezedの反映をしようと試みるがエラーになる
❯ flutter pub run build_runner build --delete-conflicting-outputs
Building package executable...
Built build_runner:build_runner.
[INFO] Generating build script completed, took 191ms
[INFO] Reading cached asset graph completed, took 187ms
[INFO] Checking for updates since last build completed, took 848ms
[SEVERE] freezed on lib/models/user.dart:
Getters require a MyClass._() constructor
package:remoi/models/user.dart:30:14
╷
30 │ String get fullName => '$lastName $firstName';
│ ^^^^^^^^
解決方法
公式のリポジトリのREADME に解決方法が記載されている
以下の一行を追加する
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
part 'user.g.dart';
@freezed
class UserModel with _$UserModel {
factory UserModel({
required String lastName,
required String firstName,
}) = _UserModel;
const UserModel._() ///////////// この一行 ////////////////
factory UserModel.fromJson(Map<String, dynamic> json) =>
_$UserModelFromJson(json);
String get fullName => '$lastName $firstName';
追加後、反映に成功する
❯ flutter pub run build_runner build --delete-conflicting-outputs
説明
For that to work, we need to define a private empty constructor. That will enable the generated code to extend/subclass our class, instead of implementing it (which is the default, and only inherits type, and not properties or methods):
これを実現するには、プライベートな空のコンストラクタを定義する必要がある。
これにより、生成されたコードがクラスを実装する(デフォルト動作であり、型のみを継承し、プロパティやメソッドは継承しない)代わりに、クラスを拡張/サブクラス化できるようになる。