👋
freezedのimmutableの仕組みメモ
dartでimmutableなオブジェクトを作成するライブラリとしてfreezedというのがある。インストールとか書き方とか機能とかは公式とか見るとして、どうimmutableになるかのメモ。
abstract class Person with _$Person{
factory Person({String name,int age}) = _Person;
}
と書くと、builder_runnerはfactoryで引数で渡されたメンバのgetterを定義したmixinの_$Personを作成する(実際にメンバが定義されているのは_$_Personでメンバはもちろんfinalで定義されている)
mixin _$Person {
String get name;
int get age;
$PersonCopyWith<Person> get copyWith;
}
とgetだけ定義されているので、
var person1 = Person(name:'hoge',age:10);
//person1.name = 'fuga'; //memberにはgetしか無いので代入できない
となり代入不可になります。変更したければ、
person1 = person1.copyWith(name:'fuga');
として別オブジェクトを作成します(copyWithも自動生成してくれています)。
freezedで作成したクラスもメンバとして渡せます。
abstract class Glasses with _$Glasses{
factory Glasses({String brand,int price}) = _Glasses;
}
abstract class Person with _$Person{
factory Person({String name,int age,Glasses glasses,MutableClass mutableClass}) = _Person;
}
var person1 = Person(name:'hoge',age:10,glasses: Glasses(brand:'メガーネ',price: 10000));
//person1.glasses = Glasses(brand:'鉄のメガーネ',price: 10); //memberにはgetしか無いので代入できない
//person1.glasses.price = 20000; //glassesもimmutableなのでそのメンバのpriceも代入できない
逆に普通にクラスも渡せるので
class MutableClass{
MutableClass(this.name);
var name;
String toString(){
return 'MutableClass($name)';
}
}
var person1 = Person(name:'hoge',age:10,glasses: Glasses(brand:'メガーネ',price: 10000),mutableClass:MutableClass('mutable1'));
var person2 = person1.copyWith(name:'fuga');
//person2.mutableClass = MutableClass('mutable2');//memberにはgetしか無いので代入できない
person2.mutableClass.name = 'mutable2'; //これはできる(MutableClassはimmutableではない)
print(person1.toString());
print(person2.toString());
とmutableClass自体はimmutableではないのでperson1.mutableClass.nameは変更できてしまう。それにより出力結果は
Person(name: hoge, age: 10, glasses: Glasses(brand: メガーネ, price: 10000), mutableClass: MutableClass(mutable2))
Person(name: fuga, age: 10, glasses: Glasses(brand: メガーネ, price: 10000), mutableClass: MutableClass(mutable2))
とperson1.mutableClass.nameの出力結果も'mutable2'となってしまう。全部immutableにしましょう。
Discussion