はじめに
ふとFlutter始めたんですが、React書いたことあると、Viewの監視対象のオブジェクトがimmutableじゃないと気になったりしませんか?
Dartでもオブジェクトの値を変化させる場合は、参照の値を変更するのでは無く、オブジェクト自体を値を変更した新たなオブジェクトで置き換えたいんです。
immutable化
探してみるとmetaパッケージの@immutableアノテーションを付け、final
なメンバとconst
付きコンストラクタを持ちいることでimmutable化することが出来そうです。
import 'package:meta/meta.dart';
@immutable
class User {
const User(this.id, this.name); // <- immutable用コンストラクタ
final int id;
final String name;
}
// User user = User() // コンパイル不可
User user = User(1, 'A');
// user.name = 'B' // コンパイル不可
user = User(user.id, 'B');
出来たことは出来たのですが、user = User(user.id, 'B');
では文脈が不明瞭なのでcopy
メソッドを用意します。
import 'package:meta/meta.dart';
@immutable
class User {
const User(this.id, this.name); // <- immutable用コンストラクタ
final int id;
final String name;
User copy({int id, String name}) {
id ??= this.id;
name ??= this.name;
return User(id, name);
}
}
User user = User(1, 'A');
user = user.copy(name: 'B'); // = User(1, 'B')
id ??= this.id
とname ??= this.name
がミソだけど、キモい。要は未定義なら自身のプロパティを当てるという意味です。
おまけ
Built Collection for Dartというパッケージを使えばListやMapもimmutable化が可能です・・・が、若干癖があるので、ほどほどに使った方が良いかも?
jsのimmutable.js感覚では使えません。