Immutable(äžå€)ããŒã¿ãšã¯ãåæååŸã®å€æŽãã§ããªãããŒã¿ã
æåå(String)ãæ°å€(int,doubleãªã©)ãboolå€(boolean)ã®å€ã¯å€æŽããããšãã§ããªãã
StringåãšããŠå泚é(åæšè«)ããã倿°ã«ã¯ãæåå(ããŒã¿)ãæ ŒçŽãããèš³ã§ã¯ãªãã
æååããŒã¿ã®ã¡ã¢ãªã®å Žæãžã®åç §ãæ ŒçŽãããã
ãšèšã£ãŠãããçè ã¯GDEã¿ãããããããã®å ¬åŒããã¥ã¡ã³ãã«ããã®ã ããããç¡ãå Žåèšèªä»æ§èŠãã°ããã®ã ãããã
final倿°ã§ãªã倿°ã¯åä»£å ¥ãå¯èœã§ãããåä»£å ¥ããã倿°ã¯ãã®æååããŒã¿ãæã瀺ãããã«ãªãããããäžåºŠçæãããæååããŒã¿èªäœ(ã®å 容ã»é·ã)ã¯å€ãããªãã
var str = "This is a string.";
str = "This is another string.";
äžèšã®ãµã³ãã«ã§ã¯strãšããåã®å€æ°ã宣èšãããŠããã
æååããŒã¿("This is a string."
)ã¯ã¡ã¢ãªã«é
眮ãããã
倿°strã«ã¯ãã®ã¡ã¢ãªã®å Žæãæ ŒçŽãããã
2è¡ç®ã§ã¯æ°ããæååããŒã¿ãçæããããã®ã¡ã¢ãªã®å Žæãstrã«æ ŒçŽãããã
æåã®æååããŒã¿èªäœã¯æ¶ããªãããã³ãŒãå ã«ãæåã®æååããŒã¿ã«ã¢ã¯ã»ã¹ã§ãã倿°ããªããªã£ãã®ã§ãunreachable(ã¢ã¯ã»ã¹äžå¯èœ)ãšããŒã¯ãããŠãDartã®ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ã«ããæçµçã«ã¯ã¡ã¢ãªãè§£æŸãããã
immutableããŒã¿ã䜿ãå©ç¹ã¯ããã€ãããã
immutableããŒã¿ã䜿ããšã¹ã¬ããã»ãŒããšãªããimmutableããŒã¿ã®å 容ãå€ããããšã¯ã§ããªãã®ã§ããããªãã³ãŒããã¢ã¯ã»ã¹ããŠããŠããããŒã¿ãåãã§ããããšãä¿èšŒãããã
åç §ãæž¡ãéã«ãé²åŸ¡çã³ããŒãããå¿ èŠããªããç¶æ ãç¶æããããã«è€éãªã³ãŒããæžãå¿ èŠããªãã®ã§å€æ°ã®äžèº«ãæšæž¬ããããã
finalãconstããŒã¯ãŒããçšãããµã³ãã«ã«ããDartã®ãã«ãã€ã³immutableæ©èœã«ã€ããŠè°è«ããŠããã
倿Žãã¹ãã§ãªãäºã€ã®ããŒã¿ã宣èšããã
Contents
Final variables vs. constants
final倿°ã¯äžåºŠã ãåæåãå¯èœãå¿ ãåæåããå¿ èŠãããã
åä»£å ¥ã¯äžå¯ã
final str = "This is a final string.";
str = "This is another string."; // ãšã©ãŒçºç
final倿°ã¯å®è¡æã«ã¹ããŒã(å€)ãæ±ºå®ãããããšã¯ããããå¿ ãåæåã«ããæ±ºå®ãããã
åä»£å ¥ã§ããªãããšä»¥å€ã¯ãæ®éã®å€æ°ãšåæ§ã®æ¯ãèãã
const宿°ã¯ã³ã³ãã€ã«æå®æ°ã
constatnt(const宿°)ã®å šäœã®ç¶æ ã¯ã³ã³ãã€ã«æã«æ±ºå®ãããã
ãªã®ã§å®è¡æã®ã³ãŒãã«ããç¶æ ã解決ãããããšã¯ãªãã
- 宿°å€(constant values)ã¯ãæ·±ããæšç§»çã«äžå€ã§ãã宿°ã³ã¬ã¯ã·ã§ã³ïŒãªã¹ããããããªã©ïŒãäœæããå Žåã¯ããã¹ãŠã®èŠçŽ ãååž°çã«å®æ°ã§ããå¿ èŠããããŸãã
宿°å€(constant values)ã¯ãã³ã³ãã€ã«æã«å©çšå¯èœãªããŒã¿ã«ããçæãããªããã°ãªããªããäŸãã°ã
DateTime.now()ã¯å®æ°ã§ã¯ãªã(å®è¡æã«ã®ã¿å©çšã§ããããŒã¿(å®è¡æã®æ¥æ)ã«ããè¿ãå€ã決ãŸã)ã®ã§ã宿°å€(constant values)ã«ã¯ãªããªãã
å®è¡æã§ãªããšå€ã決ãŸããªãâã³ã³ãã€ã«æã«å€ã決å®ã§ããªãâconstã§ã¯ãªãã
Flutterã®SizedBoxã¯finalããããã£ãšconstã³ã³ã¹ãã©ã¯ã¿ãæã£ãŠããã®ã§ã宿°å€ã«ãªãåŸãŸãã
- ä»»æã®å®æ°å€ã«å¯ŸããŠã宿°åŒãè©äŸ¡ãããåæ°ã«é¢ä¿ãªããåäžã®ãªããžã§ã¯ããã¡ã¢ãªã«äœæãããŸãã宿°ãªããžã§ã¯ãã¯å¿ èŠã«å¿ããŠåå©çšãããŸãããåäœæãããããšã¯ãããŸããã
宿°ã«é¢ãããµã³ãã«ã瀺ããŸãã
const str = "This is a constant string.";
const SizedBox(width: 10); // a constant object
const [1, 2, 3]; // a constant collection
1 + 2; // a constant expression
宿°strã¯æååãªãã©ã«ãä»£å ¥ãããŠãããæååãªãã©ã«ã¯åžžã«ã³ã³ãã€ã«æå®æ°ã
2è¡ç®ã®SizedBoxã€ã³ã¹ã¿ã³ã¹ã¯constantã§immutableã§ãã
Dartã¯ããã°ã©ã å®è¡åã«SizedBoxã€ã³ã¹ã¿ã³ã¹ãã»ããã¢ããã§ããããã§ããSizedBoxã®å šãŠã®ããããã£ãfinalã§ãããåŒæ°ãšããŠæ°å€ãªãã©ã«(宿°)ãæž¡ããŠããããã§ãã
3è¡ç®ã®constantãªãªã¹ããªãã©ã«ãåé¡ãããŸãããå šãŠã®èŠçŽ ãconstant(æ°å€ãªãã©ã«)ã ããã§ãã
4è¡ç®ã®1+2ãã³ã³ãã€ã«æã«Dartãèšç®ããã®ã§ãconstantãšèšããŸãã
constantã¯æ£èŠåãããDartã¯ããã©ã«ãã§identityãæ¯èŒããŸãã®ã§ãäºã€ã®å¥ã ã®å®æ°ã€ã³ã¹ã¿ã³ã¹ã«èŠãã以äžã®ã³ãŒãã¯çå€ãšè©äŸ¡ãããŸããã¡ã¢ãªã«ãããŠå šãåããã®ãåç §ããŠããããã§ãã
List<int> get list => [1, 2, 3];
List<int> get constList => const [1, 2, 3];
var a = list;
var b = list;
var c = constList;
var d = constList;
print(a == b); // false
print(c == d); // true
Dartã¯ãèŠçŽ ã®å€ãçããã?ããæ¯èŒããŠããã®ã§ã¯ãªããã¡ã¢ãªã®ã¢ãã¬ã¹(åç §)ãåãããèŠãŠããŸããconstListã²ãã¿ãŒã®åŒã³åºãã¯åžžã«constantãªãªã¹ã
const [1,2,3]
ãžã®åç §ãè¿ããŸãã
ã ããc==dã¯trueãšãªãã
Dartã¯ã¡ã¢ãªã«ãªã¹ã( const [1,2,3] )ãäžåºŠã ãé 眮ããŸãã(constã ãã)
次ã«Flutterãã¬ãŒã ã¯ãŒã¯ãimmutableããŒã¿ãã©ã®ããã«å©çšããŠããããèŠãŠãããŸãã
Immutable data in Flutter
Flutterã¢ããªã±ãŒã·ã§ã³ãäžå€(immutable)ã®æ§é ãå©çšããŠèªã¿ããããããã©ãŒãã³ã¹ãåäžãããããšãã§ããå Žæã¯ãããããããŸããäžå€(immutable)ã®åœ¢åŒã§æ§ç¯ã§ããããã«ãå€ãã®ãã¬ãŒã ã¯ãŒã¯ã¯ã©ã¹ãäœæãããŠããŸãã2ã€ã®äžè¬çãªäŸã¯ãSizedBoxãšTextã§ãã
Row(
children: <Widget>[
const Text("Hello"),
const SizedBox(width: 10),
const Text("Hello"),
const SizedBox(width: 10),
const Text("Can you hear me?"),
],
)
äžèšãµã³ãã«ã®ããã«ãconst
ããŒã¯ãŒãã䜿çšããŠconst
ã³ã³ã¹ãã©ã¯ã¿ãŒãæã€ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãäœæãããšïŒè©³çްã¯åŸã§èª¬æããŸãïŒãå€ã¯ã³ã³ãã€ã«æã«äœæãããäžæã®åå€ã¯1åã ãã¡ã¢ãªã«æ ŒçŽãããŸãã
æåã®2ã€ã®Textã€ã³ã¹ã¿ã³ã¹ã¯ã2ã€ã®SizedBoxã€ã³ã¹ã¿ã³ã¹ãšåæ§ã«ãã¡ã¢ãªå ã®åããªããžã§ã¯ããžã®åç §ã«è§£æ±ºãããŸãã
const SizedBox(width:15)
ã远å ãããšãconstantãªã€ã³ã¹ã¿ã³ã¹ãçæãããŸãã
constããŒã¯ãŒãã䜿çšããã«ããããã¹ãŠã®ã€ã³ã¹ã¿ã³ã¹ãçæã§ããŸããããã¯new
ã䜿ã£ãŠããããšãšåãã§ãã衚é¢çã«ã¯(constã䜿ã£ãŠã䜿ããªããŠã)åãããã«æ©èœããããã«èŠããŸãããã¢ããªã®ã¡ã¢ãªãããããªã³ããåæžããã©ã³ã¿ã€ã ããã©ãŒãã³ã¹ãåäžãããããã«ãã§ããéãconstã䜿çšããããšããå§ãããŸãã
å¥ã®Textã䜿ã£ããµã³ãã«ãèŠãŠã¿ãŸãããã
final size = 12.0; //âãããconstã§å®£èšããã°ãšã©ãŒã¯åºãªããªãã
const Text(
"Hello",
//âTextStyleãçæããããšããŠããããconstããŒã¯ãŒãã䜿ã£ãŠããªãã
style: TextStyle(
fontSize: size, // ãšã©ãŒçºç
),
)
constããŒã¯ãŒãã䜿ã£ãŠconstantãªTextã€ã³ã¹ã¿ã³ã¹ãçæããããšããŠããŸãããããconstantã¯ãã®å šãŠãconstant(ã³ã³ãã€ã«æã«å€ã決ãŸã)ã§ãªããã°ãªããŸããã
æååãªãã©ã«”Hello”ã¯constantãªã®ã§åé¡ãããŸããã
äžèšãµã³ãã«ã§ã¯ãTextStyleã€ã³ã¹ã¿ã³ã¹çæç®æã§constããŒã¯ãŒãã䜿çšããŠããŸããããããã§ãDartã¯TextStyleã€ã³ã¹ã¿ã³ã¹ã宿°(constant)ãšããŠçæããããšããŸãã(Dartã¯ã宿°ã§ããTextã€ã³ã¹ã¿ã³ã¹ã®ãã£ãŒã«ãã§ããTextStyleã€ã³ã¹ã¿ã³ã¹ã宿°ã§ãªããã°ãªããªãããšããããšãç¥ã£ãŠãããã)
ã§ãTextStyleã€ã³ã¹ã¿ã³ã¹ã¯constant(宿°)ã«ã¯ãªããŸããããªããªãTextStyleã³ã³ã¹ãã©ã¯ã¿ã«å€æ°sizeãæž¡ãããŠããããã§ãã
倿°sizeã¯final倿°ãªã®ã§ãå®è¡æã«å€ã決å®ãããã(ïŒå®è¡æã§ãªããšå€ã決å®ãããªãã)
ãšããããšã§ãšã©ãŒãçºçããããããä¿®æ£ããã«ã¯ã
- TextStyleã³ã³ã¹ãã©ã¯ã¿ã«æž¡ãå€ã§ãã倿°sizeãconstã§å®£èšãã
- TextStyleã³ã³ã¹ãã©ã¯ã¿ã«12.0ãªã©ã®æ°å€ãªãã©ã«ãæž¡ã
ã©ã¡ãããããå¿ èŠãããã
æã«ã¢ããªã®ç¶æ ããŒã¿ãäºæããªã倿Žããå®ãå¿ èŠãããå ŽåããããŸããæ¬¡ã«ãDartã§ãããå®çŸããæ¹æ³ãèããŠããã
Creating your own immutable data classes
ã·ã³ãã«ãªimmutableãªã¯ã©ã¹ãå®çŸ©ããã«ã¯ã
finalãªããããã£
constã³ã³ã¹ãã©ã¯ã¿
ãçšæããŸãã
class Employee {
final int id;
final String name;
const Employee(this.id, this.name);
}
Employeeã¯ã©ã¹ã®äºã€ã®ããããã£
id
name
ã¯ã©ã¡ããã³ã³ã¹ãã©ã¯ã¿ã«ããèªåçã«åæåãããã
ã³ã³ã¹ãã©ã¯ã¿ã¯constããŒã¯ãŒãã䜿ã£ãŠå®£èšãããŠãããããã«ããDartã¯ããã®ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãconstã³ã³ã¹ãã©ã¯ã¿ã䜿ã£ãŠçæããæã«ãã³ã³ãã€ã«æå®æ°ãšããŠçæããŸãã
const emp1 = Employee(1, "Jon");
var emp2 = const Employee(1, "Jon");
final emp3 = const Employee(1, "Jon");
äžèšãµã³ãã«ã§å¯äžã®constantãªEmployeeã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãçæãããããããã®å€æ°(宿°)ã«åç §ãä»£å ¥ãããŸãã
emp1ã«ãããŠãã³ã³ã¹ãã©ã¯ã¿ã«constããŒã¯ãŒããä»ããå¿ èŠã¯ãããŸããã倿°å®£èšã§constããŒã¯ãŒããä»ããŠããããã§ãã
ã€ãŸãå¿ ç¶çã«constã«ãªãéšåã¯constããŒã¯ãŒããçç¥ã§ããããšããããšã
ãããä»ãããã®ã§ããã°ã³ã³ã¹ãã©ã¯ã¿ã«ãconstããŒã¯ãŒããä»ããŠãæ§ããŸããã
emp2ã«é¢ããŠãemp2ã¯Employeeåã®éåžžã®å€æ°ã§ãããã®éåžžã®å€æ°ã«ãimmutableãª(constãä»ããŠçæããã)宿°ãªããžã§ã¯ããžã®åç §ãä»£å ¥ããŠããŸãã
emp3ã¯ãfinalã§å®£èšãããŠããŸãã®ã§ããã®åŸã«å¥ã®åç §ãä»£å ¥ããããšã¯ã§ããŸããããã以å€ã¯emp2ãšåãã§ãã
ãããã®åç §ãã©ãã§æž¡ãããšããŠãã調ã¹ãã°ãã€ã§ããªããžã§ã¯ãã®idã¯1ã§ãããname㯔Jon”ã§ããããšã確å®ã§ãããããŠã¡ã¢ãªäžã§åãå€ã調ã¹ãŠããããšã«ãªããŸãã
ããŒã¿ã¯ã©ã¹ã®finalããããã£ããã©ã€ããŒãã«ããããšã¯äžè¬çã§ã¯ãªãããšã«æ³šæããŠãã ããããããã¯å€æŽã§ãããããããžã®èªã¿åãã¢ã¯ã»ã¹ãå¶éããããšã«ãã£ãŠåŸããããã®ã¯å€ããããŸããã詮玢奜ããªã³ãŒãããå€ãé ãçç±ãããå ŽåããŸãã¯å éšç¶æ ãã¯ã©ã¹ã®ãŠãŒã¶ãŒãšç¡é¢ä¿ã§ããå Žåã¯ããã©ã€ãã·ãŒãæ€èšãã䟡å€ããããããããŸããã
immutableãªã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ãçæããã®ã«æåããæã«ããããDartãã¬ãŒã ã¯ãŒã¯ãçè§£ããå©ãã«ãªãæ¹æ³ã«é¢ããŠã以äžã«ç€ºããŸãã
Using a metatag helper
metaããã±ãŒãžã®@immutable
ã¡ã¿ã¿ã°ã䜿çšããŠãimmutable(äžå€)ã«ããäºå®ã®ã¯ã©ã¹ã«é¢ããæçšãªã¢ãã©ã€ã¶ãŒèŠåãååŸã§ããŸãã
import 'package:meta/meta.dart';
@immutable
class Employee {
int id; // not final
final String name;
Employee(this.id, this.name);
}
@immutableã¿ã°ãä»ããã ãã§immutableãªã¯ã©ã¹ã«ãªãèš³ã§ã¯ãããŸããã
ããã@immutableã¿ã°ã䜿ããšãäžèšã®ãµã³ãã«ã®ããã«ãfinalã§ãªããã£ãŒã«ããããå Žåããäžã€ä»¥äžã®finalã§ãªããã£ãŒã«ãããããæšã®èŠåãåŸãããŸãã
@immutableã¿ã°ã䜿ããšãmutableãªãã£ãŒã«ããããæã«ã³ã³ã¹ãã©ã¯ã¿ã«constããŒã¯ãŒãã远å ãããšããšã©ãŒãçºçããŸãã
@immutableã¿ã°ã䜿ã£ãŠããã¯ã©ã¹ã®ãµãã¯ã©ã¹ãimmutableã§ãªãå Žåã«èŠåãåŸãããŸãã
äžå€æ§ã«ã€ããŠããªããžã§ã¯ããšã³ã¬ã¯ã·ã§ã³ã¯å°ã話ãè€éã«ãªããŸãã
ãããã«é¢ããŠèŠãŠãããŸãããã
Complex objects in immutable classes
employeeã¯ã©ã¹ã®nameããããã£ãStringåã§ã¯ãªããããå°ãè€éãªEmployeeNameã¯ã©ã¹ã§è¡šãããå Žåã©ããªãã§ãããã?
äŸãã°ä»¥äžã®ãããªæãã§ãã
class EmployeeName {
String first;
String middleInitial;
String last;
EmployeeName(this.first, this.middleInitial, this.last);
}
Employeeã¯ã©ã¹ã¯ä»¥äžã®ããã«ãªããŸãã
class Employee {
final int id;
final EmployeeName name;
const Employee(this.id, this.name);
}
ã»ãšãã©ã®å ŽåãEmployeeã¯ã©ã¹ã¯ä»¥åãšåãããã«æ©èœããŸãããéèŠãªéãã1ã€ãããŸããEmployeeNameã¯ã©ã¹ãimmutableãªã¯ã©ã¹ãšããŠå®çŸ©ããŠããªãããããã®ããããã£ã¯åæååŸã«å€æŽãããå¯èœæ§ããããŸãã
var emp = Employee(1, EmployeeName('John', 'B', 'Goode'));
emp.name = EmployeeName('Jane', 'B', 'Badd'); // (1)blocked
emp.name.last = 'Badd'; // (2)allowed
emp.nameã¯finalã§å®£èšãããŠããã®ã§ã(1)ã®åŠçã¯ã§ããªã(ãšã©ãŒçºç)ã
Employeeã¯ã©ã¹ã¯immutableãªã¯ã©ã¹ãšããŠå®çŸ©ãããŠãããemp.nameã¯finalã§å®£èšãããŠãããã(2)ã®åŠçã¯ã§ããŠããŸãã
äžèšã®èª¬æã¯çŽæ¥emp.nameã®ãã£ãŒã«ãã倿ŽããŠããäŸããããããããäžèšã®ãµã³ãã«ããããã«ãã倿Žã®äŸãšããŠæãããããšæãããã
class EmployeeName { String first; String middleInitial; String last; EmployeeName(this.first, this.middleInitial, this.last); } class Employee { final int id; final EmployeeName name; const Employee(this.id, this.name); } void main(){ var emp1=Employee(12,EmployeeName("fir","mid","las"),); var emp2=emp1; //ä»£å ¥(ã³ããŒ) emp2.name.first="yyy"; print(emp1.name.first); // yyy print(emp2.name.first); // yyy //emp2.name.firstã倿Žããæã«emp1.name.firstã //倿Žãããããšãèªèã§ããŠããã°è¯ããã //ã§ããŠããªããšãèŠã€ããã«ããäžå ·åãçºçããããšã«ãªãã //ãEmployeeNameã¯ã©ã¹ã®å šãŠã®ãã£ãŒã«ããfinalã«ããŠã //EmployeeNameã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ãconstã³ã³ã¹ãã©ã¯ã¿ã«ããŠã //Employeeã¯ã©ã¹èªäœconstãšããŠçæãããã°åœç¶å€æŽã§ããªããªãã //ãããŸã§ããªããŠãããEmployeeNameã¯ã©ã¹ã®å šãŠã®ãã£ãŒã«ããfinal //ã«ãããã ãã§ããåä»£å ¥ã§ããªããªãã®ã§ã"yyy"ã«å€æŽããããšã¯ã§ããªããªãã }
class Employee { final int id; final EmployeeName name; const Employee(this.id, this.name); } class EmployeeName { String first; String middleInitial; String last; EmployeeName(this.first, this.middleInitial, this.last); } void main() { var emp = Employee(1, EmployeeName('John', 'B', 'Goode')); print(emp.name.last); //'Goode' //emp.name = EmployeeName('Jane', 'B', 'Badd'); // blocked emp.name.last = 'Badd'; // allowed print(emp.name.last); //'Badd' }
çµå±äžèšã®ã³ãŒãã§ã¯Employeeã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ã¯constã³ã³ã¹ãã©ã¯ã¿ã ããEmployeeNameã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ãconstã³ã³ã¹ãã©ã¯ã¿ã§ã¯ãªãã®ã§ãEmployeeã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ãconstã³ã³ã¹ãã©ã¯ã¿ãšããŠåŒã³åºãããšã¯ã§ããªããã€ãŸãâ
var emp = const Employee(1, EmployeeName('John', 'B', 'Goode')); /* ãšã©ãŒçºç The constructor being called isn't a const constructor - */
âã®ãããªåŒã³åºãã¯ã§ããªããEmployeeãã³ã³ãã€ã«æå®æ°ãšããŠ(constãšããŠ)çæããã«ã¯ãã®ããããã£ãå šãŠconstã§ããå¿ èŠãããã
https://dart.dev/guides/language/language-tour#final-and-const
 Note: Although aÂ
final
 object cannot be modified, its fields can be changed. In comparison, aÂconst
 object and its fields cannot be changed: theyâre immutable.ãã®ããŒãžã®ååã§ã説æããŠããã
ãããEmployeeNameã¯ã©ã¹ã«constã³ã³ã¹ãã©ã¯ã¿ã¯å®çŸ©ãããŠããªãã®ã§ãEmployeeNameã€ã³ã¹ã¿ã³ã¹ãconstã§çæããããšã¯ã§ããªãããšããããšã§ãEmployeeã€ã³ã¹ã¿ã³ã¹ãconstã³ã³ã¹ãã©ã¯ã¿ã§ã¯çæã§ããªãã
Employeeã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ã¯constã³ã³ã¹ãã©ã¯ã¿ãšããŠå®çŸ©ãããŠããããconstãä»ããã«ã³ã³ã¹ãã©ã¯ã¿ãåŒã³åºããšconstã§ãªãã€ã³ã¹ã¿ã³ã¹ãçæãããã
https://dart.dev/guides/language/language-tour#using-constructors
If a constant constructor is outside of a constant context and is invoked withoutÂ
const
, it creates a non-constant object:
Employeeã¯ã©ã¹ã®nameããããã£ã¯finalã§å®£èšãããŠããã®ã§ãemp.nameãžã®åä»£å ¥ã¯ã§ããŸãã(1)ã
ããããEmployeeNameã¯ã©ã¹ã®ããããã£ã¯ãEmployeeã¯ã©ã¹ãšã¯éã£ãŠfinalã§å®£èšãããŠããŸãããã§ããã(2)ã®ãããªä»£å ¥ã¯ã§ããŠããŸããŸãã
åŸæ¥å¡ããŒã¿ãäžå€ã§ãããšæåŸ ããŠããå Žåãããã¯æå³ããªãè匱æ§ã§ããå¯èœæ§ããããŸãããã®åé¡ã解決ããã«ã¯ãããŒã¿æ§æã§äœ¿çšããããã¹ãŠã®ã¯ã©ã¹ãäžå€ã§ããããšã確èªããŠãã ããã
Immutable collections
ã³ã¬ã¯ã·ã§ã³ã¯ãäžå€æ§ã«å¯Ÿããå¥ã®èª²é¡ãæç€ºããŸããfinal
ã«ãããªã¹ããããããžã®åç
§ã§ãã£ãŠãããããã®ã³ã¬ã¯ã·ã§ã³å
ã®èŠçŽ ã¯ãŸã 倿Žå¯èœã§ãããŸããDartã®ãªã¹ããšãããã¯ãããèªäœã倿Žå¯èœãªè€éãªãªããžã§ã¯ãã§ãããããèŠçŽ ã远å ãåé€ããŸãã¯äžŠã¹æ¿ããããšãã§ããŸãã
ãã£ããã¡ãã»ãŒãžããŒã¿ã®ã·ã³ãã«ãªãµã³ãã«ãèããŠã¿ãŸãããã
class Message {
final int id;
final String text;
const Message(this.id, this.text);
}
class MessageThread {
final List<Message> messages;
const MessageThread(this.messages);
}
ãã®èšå®ã§ã¯ãããŒã¿ã¯ããªãå®å šã§ãã
ç¬èªå®çŸ©ããã¯ã©ã¹ã¯å šãŠimmutableãªã¯ã©ã¹ãšããŠå®çŸ©ãããŠããã
äœæããããã¹ãŠã®ã¡ãã»ãŒãžã¯äžå€ã§ãããäžåºŠåæåããããšãMessageThreadå ã®ã¡ãã»ãŒãžã®ãªã¹ãã眮ãæããããšã¯ã§ããŸããããã ãããªã¹ãæ§é ã¯å€éšã³ãŒãã§æäœã§ããŸãã
ããªã¹ãæ§é ãæäœã§ãããç¶æ ã¯ãäžè¬çãªèšèã®äœ¿ãæ¹ãšããŠããªã¹ãã眮ãæããããšãã§ããããšèšãããããªæ°ããããã説æããããšããŠããããšã¯ãããã
final thread = MessageThread([
Message(1, "Message 1"),
Message(2, "Message 2"),
]);
thread.messages.first.id = 10; // blocked
thread.messages.add(Message(3, "Message 3")); // Uh-oh. This works!
ããããããªããæå³ãããã®ã§ã¯ãããŸãããã§ã¯ãã©ãããã°ãããé²ãããšãã§ããŸããïŒå©çšå¯èœãªããã€ãã®ç°ãªãæŠç¥ããããŸãã
äžèšèª¬æã¯çŽæ¥threadã®äžèº«ã倿ŽããŠããäŸãããããããã以äžã®ãããªã±ãŒã¹ããããã«ããäŸãšããŠæãããããšæãããã
class Message { final int id; final String text; const Message(this.id, this.text); } class MessageThread { final List<Message> messages; const MessageThread(this.messages); } void main(){ final thread = MessageThread([ Message(1, "Message 1"), Message(2, "Message 2"), ]); var ot=thread; //âä»£å ¥(ã³ããŒ) ot.messages[0]=Message(-1,"xxxxx"); print(thread.messages[0].id); // -1 //äžèšã®ãããªå€æŽã§ã³ããŒå ã®threadã®äžèº«ãŸã§ //倿ŽãããŠããããšãèªèã§ããŠããªããšã //äžå ·åãèŠã€ããã«ããã //倿Žã§ããªãããã«ããæ¹æ³ãšããŠãMessageThreadã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ã //constã³ã³ã¹ãã©ã¯ã¿ãšããŠå®çŸ©ãããŠããã®ã§ã //MessageThreadã€ã³ã¹ã¿ã³ã¹ãconstãšããŠå®çŸ©ããã°å€æŽã§ããªãã //ãããããªãã®ã§ããã°ãä»ãŸã§èª¬æãããããã«ãªã¹ãã®èŠçŽ ã倿Žå¯èœãªã®ã§ //ãã®å¯ŸçãšããŠãã®åŸèª¬æãããããªããã©ã€ããŒã+ã³ããŒãè¿ãã²ãã¿ãŒã //ã®ãããªæ¹æ³ãå¿ èŠããšãã話ã }
class Message { int id; String text; Message(this.id, this.text); } class MessageThread { final List<Message> _messages; List<Message> get messages => _messages.toList(); const MessageThread(this._messages); } void main(){ final thread = MessageThread([ Message(1, "Message 1"), Message(2, "Message 2"), ]); var messages2=thread.messages; messages2.first.text="xxxxx"; print(thread.messages[0].text); //xxxxx /* Messageã¯ã©ã¹ã®ãã£ãŒã«ããfinalãããªãå Žåã äžèšã®ãããªå€æŽãthreadã«åæ ãããã MessageThreadã¯ã©ã¹ã®ã²ãã¿messages㯠ã·ã£ããŒã³ããŒãè¿ãã®ã§ã messages2.first.textãžã®ä»£å ¥ãã thread.messages[0].textã«ãåæ ãããã */ }
class Message { int id; String text; Message(this.id, this.text); } class MessageThread { final List<Message> _messages; List<Message> get messages => _messages.toList(); const MessageThread(this._messages); } void main(){ final thread = MessageThread([ Message(1, "Message 1"), Message(2, "Message 2"), ]); var thread2=thread; thread2.messages[0].text="yyyyy"; print(thread.messages[0].text); /* Messageã¯ã©ã¹ã®ãã£ãŒã«ããfinalãããªãå Žåã äžèšã®ãããªå€æŽãthreadã«åæ ãããã MessageThreadã¯ã©ã¹ã®ã²ãã¿messages㯠ã·ã£ããŒã³ããŒãè¿ãã®ã§ã thread2.messages[0].textãžã®ä»£å ¥ãã thread.messages[0].textã«ãåæ ãããã */ }
class Message { int id; String text; Message(this.id, this.text); @override toString()=>"$id:$text"; } class MessageThread { final List<Message> _messages; List<Message> get messages => _messages.toList(); const MessageThread(this._messages); } void main(){ final thread = MessageThread([ Message(1, "Message 1"), Message(2, "Message 2"), ]); var messages2=thread.messages; messages2.first=Message(100,"zzzzz"); print(thread.messages.first); print(messages2.first); /* ã²ãã¿messagesãã·ã£ããŒã³ããŒãè¿ãã®ã§äžèšã®ä»£å ¥ã¯ thread.messages.firstã«ã¯åæ ãããªãã */ }
Return a copy of the collection
åŒã³åºãå ã®ã³ãŒããã³ã¬ã¯ã·ã§ã³ã®å€æŽå¯èœãªã³ããŒãåãåãããšãæ°ã«ããªãå Žåã¯ãDartã²ãã¿ãŒã䜿çšããŠãã¯ã©ã¹ã®å€éšããã¢ã¯ã»ã¹ããããã³ã«ãã¹ã¿ãŒãªã¹ãã®ã³ããŒãè¿ãããšãã§ããŸãã
class MessageThread {
final List<Message> _messages;
List<Message> get messages => _messages.toList();
const MessageThread(this._messages);
}
thread.messages.add(Message(3, "Message 3")); // new list
ãã®MessageThreadã¯ã©ã¹ã§ã¯ãå®éã®ã¡ãã»ãŒãžãªã¹ãã¯ãã©ã€ããŒãã§ããã³ã³ã¹ãã©ã¯ã¿ãŒãä»ããŠäžåºŠã ãèšå®ã§ããŸãã_messagesãªã¹ãã®ã³ããŒãè¿ãmessagesãšããååã®ã²ãã¿ãŒãå®çŸ©ãããŠããŸããå€éšã³ãŒãããªã¹ãã®add()
ã¡ãœãããåŒã³åºãå Žåããªã¹ãã®å¥ã®ã³ããŒã§åŒã³åºããããå
ã®ã³ãŒãã¯å€æŽãããŸãããã³ããŒããããªã¹ãã¯æ°ããã¡ãã»ãŒãžãæã€ãªã¹ãã«ãªããŸãããMessageThreadãªããžã§ã¯ãå
ã®_messagesãªã¹ãã¯å€æŽãããŸããã
ããã©ã€ããŒãã«ããã+ãã²ãã¿ã®ã¿çšæãããâã€ãã¥ãŒã¿ãã« ã«ã§ããããšãã話ã
ãã®ã¢ãããŒãã¯åçŽã§ãããæ¬ ç¹ããªãããã§ã¯ãããŸããã
ãŸãããªã¹ããéåžžã«å€§ããããé »ç¹ã«ã¢ã¯ã»ã¹ãããšãããã©ãŒãã³ã¹ã«è² æ
ããããå¯èœæ§ããããŸãããªã¹ãã®ã·ã£ããŒã³ããŒ(shallow copy)ã¯ãmessages
ã«ã¢ã¯ã»ã¹ããããã³ã«äœæãããŸãã
次ã«ãå ã®ãªã¹ãã®å€æŽãèš±å¯ãããŠããããã«èŠãããããã¯ã©ã¹ã®ãŠãŒã¶ãŒã«ãšã£ãŠæ··ä¹±ãæãå¯èœæ§ããããŸãã圌ãã¯ã³ããŒãè¿ãããŠããããšã«æ°ä»ããŠããªããããããŸãããããã«ãããã¢ããªã§é©ãã¹ãåäœãçºçããå¯èœæ§ããããŸãã
Return an unmodifiable collection or view
ããŒã¿ã¯ã©ã¹å ã®ã³ã¬ã¯ã·ã§ã³ãžã®å€æŽãé²ãå¥ã®æ¹æ³ã¯ãã²ãã¿ãŒã䜿çšããŠå€æŽäžå¯èœãªããŒãžã§ã³ãŸãã¯å€æŽäžå¯èœãªãã¥ãŒãè¿ãããšã§ãã
class MessageThread {
final List<Message> _messages;
List<Message> get messages => List.unmodifiable(_messages);
const MessageThread(this._messages);
}
thread.messages.add(Message(3, "Message 3")); // exception!
ãã®ã¢ãããŒãã¯äžã€åã®ã¢ãããŒããšéåžžã«äŒŒãŠããŸãããªã¹ãã®ã³ããŒãçæããã®ã¯åãã§ãããããä»åè¿ãã³ããŒã¯unmodifiableã§ããDartã®Listã¯ã©ã¹ã§å®çŸ©ãããŠããfactoryã³ã³ã¹ãã©ã¯ã¿ã䜿ã£ãŠæ°ãããªã¹ããçæããŸãã
ã¯ã©ã¹ã®ãŠãŒã¶ãŒããã²ãã¿ãŒmessagesã§è¿ããããªã¹ãã«å¥ã®ã¡ãã»ãŒãŒãžã远å ããããšãããšãå®è¡æãšã©ãŒãçºçãã远å ã¯æåŠãããŸãã
äžã€åã®ã¢ãããŒãããã¯ãŸãã§ããããŸã æ¬ ç¹ããããŸãã
å®è¡æã«add()ã®åŒã³åºãã倱æããŠDartã¢ãã©ã€ã¶ãŒããã®èŠåããããŸããããŠãŒã¶ãŒã¯ãçŽæ¥åç §ã§ã¯ãªããªã¹ãã®ã³ããŒãåä¿¡ããŠââããŸãããããã¯èªèãããŠããªãå¯èœæ§ããããŸãã
dart:collection
ã©ã€ãã©ãªã®UnmodifiableListViewã¯ã©ã¹ã䜿çšããŠãã¢ãããŒããå°ãæ¹åã§ããŸãã
import 'dart:collection';
class MessageThread {
final List<Message> _messages;
UnmodifiableListView<Message> get messages =>
UnmodifiableListView<Message>(_messages);
const MessageThread(this._messages);
}
thread.messages.add(Message(3, "Message 3")); // exception!
UnmodizableListViewã¯å ã®ãªã¹ãã®ã³ããŒãäœæããªãããããã®æ¹æ³ã§å®è¡ãããšãããã©ãŒãã³ã¹ãå°ãåäžããå¯èœæ§ããããŸãã代ããã«ã倿Žãé²ããã¥ãŒã§ãªãªãžãã«ãã©ããããŸããæ®å¿µãªãããéåã¯å®è¡æã«äŸå€ã®åœ¢ã§ã®ã¿å ±åãããŸãããList.unmodifiable()ã«ãã£ãŠæäŸããããã®ãããå°ã説æçãªãã®ã§ãããŸã ããã€ãã®æ¬ ç¹ããããŸããããã®ã¢ãããŒãã¯å€ãã®ç¶æ³ã«åå察å¿ã§ããããããœãªã¥ãŒã·ã§ã³ãšããŠéåžžã«äººæ°ããããŸãã
ä»ã®ã³ã¬ã¯ã·ã§ã³ã¿ã€ãã¯ã©ãã§ããïŒMapãSetãªã©ã®ä»ã®ã³ã¬ã¯ã·ã§ã³ã«ã
unmodifiable()
Âfactory
ã³ã³ã¹ãã©ã¯ã¿ãŒãããããããã®å€æŽäžå¯èœãªãã¥ãŒã¯dart:collection
ã©ã€ãã©ãªã§å©çšã§ããŸãã
ã³ã¬ã¯ã·ã§ã³ãžã®å€æŽãé²ãããã«èæ ®ãã¹ãããšãããã€ããããŸãã
Truly immutable collections
ã²ãã¿ãŒã䜿çšããŠã³ã¬ã¯ã·ã§ã³ã®äžå€ããŒãžã§ã³ãè¿ãããã®ãã¹ãŠã®ããªãã¯ã¯ãå
ã®ã³ã¬ã¯ã·ã§ã³ã倿Žå¯èœãªç¶æ
ã®ãŸãŸã ãšããããšã«æ°ä»ãããããããŸãããã©ã€ãã©ãªå
ã®ã³ãŒãã¯ããã©ã€ããŒããª_messages
ãªã¹ãã®æ§é ãæäœã§ããŸããããã¯åé¡ãªããããããŸããããçŽç²äž»çŸ©è
ã¯ããã§ãæäœäžå¯èœã§ããããšãæããããããŸããã
äžã€ã®æ¹æ³ã¯ãMessageThreadãªããžã§ã¯ãçææã«ããªã¹ããunmodifiableãªãã®ãšããŠçæããããšã§ãã
class MessageThread {
final List<Message> messages;
const MessageThread._internal(this.messages);
factory MessageThread(List<Message> messages) {
return MessageThread._internal(List.unmodifiable(messages));
}
}
æåã«è¡ãå¿
èŠãããã®ã¯ãã©ã€ãã©ãªã®å€éšã®ã³ãŒããã宿°ã³ã³ã¹ãã©ã¯ã¿ãŒãã¢ã¯ã»ã¹äžå¯ã«ããããšã§ããã¢ã³ããŒã¹ã³ã¢ãã¬ãã£ãã¯ã¹ãä»ããååä»ãã³ã³ã¹ãã©ã¯ã¿ãŒã«å€æŽãããã©ã€ããŒãã«ããŸããMessageThread._internal()
ã³ã³ã¹ãã©ã¯ã¿ã¯ãç§ãã¡ã®å€ãããã©ã«ãã³ã³ã¹ãã©ã¯ã¿ããããŸã£ããåãä»äºãããŸãããã¯ã©ã¹å
ããã®ã¿ã¢ã¯ã»ã¹ããããšãã§ããŸãã
factoryã³ã³ã¹ãã©ã¯ã¿ã¯staticã¡ãœããã«äŒŒãŠããŸããéåžžã®ã³ã³ã¹ãã©ã¯ã¿ã®ããã«èªåçã«è¿ãã®ã§ã¯ãªããã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãæç€ºçã«è¿ãå¿ èŠããããšããç¹ã§ã
finalãªããããã£ãåæåããåã«ãåãåã£ãã¡ãã»ãŒãžã®ãªã¹ããunmodifiableãªãã®ã«èª¿æŽããå¿ èŠãããã®ã§ãããã¯äŸ¿å©ãªéãã§ãã
ãã¡ã¯ããªã³ã³ã¹ãã©ã¯ã¿ã¯ãã€ã³ã¹ã¿ã³ã¹ãäœæãããã©ã€ããŒãã³ã³ã¹ãã©ã¯ã¿ã«æž¡ãåã«ãåä¿¡ãªã¹ãã倿Žäžå¯èœãªãªã¹ãã«ã³ããŒããŸãããŠãŒã¶ãŒã¯ããã€ããšåãæ¹æ³ã§ã€ã³ã¹ã¿ã³ã¹ãäœæãããããããã«æ°ä»ããŸããã
å šãåãæ¹æ³ã§MessageThreadã€ã³ã¹ã¿ã³ã¹ãçæããŠããããfactoryã³ã³ã¹ãã©ã¯ã¿ã䜿ã£ããµã³ãã«ã§ã¯ãmessagesãã£ãŒã«ãã«ãunmodifiableãªãªã¹ããã»ãããããã
final thread = MessageThread([
Message(1, "Message 1"),
Message(2, "Message 2"),
]);
ããã¯åŒãç¶ãæ©èœããïŒãœãŒã¹ãèŠããã«ïŒéåžžã®ã³ã³ã¹ãã©ã¯ã¿ãŒã§ã¯ãªããã¡ã¯ããªãŒã³ã³ã¹ãã©ã¯ã¿ãŒãåŒã³åºããŠããããšã誰ãç¥ãããšãã§ããŸãããã¡ãªã¿ã«ããã®ææ³ã¯Dartã®ã·ã³ã°ã«ãã³ãã¶ã€ã³ãã¿ãŒã³ã«äœ¿çšãããŠããææ³ãšäŒŒãŠããŸãã
ä¿åããããªã¹ãã¯å€æŽã§ããªããããåãã¯ã©ã¹ãŸãã¯ã©ã€ãã©ãªå ã®ã³ãŒãã§ãã倿Žã§ããŸããããã ããããŒã¿ãæŽæ°ããªããŠãæå³ã®ããããšãå®è¡ã§ããã¢ããªã¯ããã»ã©å€ããããŸããã
immutableãªããŒã¿ãå®å šã«æŽæ°ããã«ã¯ã©ãããã°ããã§ããããã
Updating immutable data
ãã¹ãŠã®ã¢ããªã®ç¶æ ãäžå€ã®æ§é ã«å®å šã«é ããŠãããšãã©ã®ããã«æŽæ°ã§ããã®ãçåã«æããããããŸãããã¯ã©ã¹ã®åã ã®ã€ã³ã¹ã¿ã³ã¹ã¯ïŒå°ãªããšãå€éšããïŒå€æŽå¯èœã§ãã£ãŠã¯ãªããŸããããç¶æ ã¯ç¢ºãã«å€æŽããå¿ èŠããããŸããçžå€ããããããã€ãã®ç°ãªãã¢ãããŒãããããããã§ãããã®ããã€ããæ¢æ±ããŸãã
ããããå ã«ããã£ãŒã«ããint,Stringåã®ã¿ã®Employeeã¯ã©ã¹ã«ã€ããŠã®èª¬æãããããçŸæç¹ã§ã®èªèãšããŠããã£ãŒã«ããããªããã£ãåã®ã¿ã§ããã°ãå šãŠã®ãã£ãŒã«ããfinalã«ããŠããã°ãæŽæ°é¢æ°ãããªãããã ã®ä»£å ¥ã§ãããã®åŸæå³ãã¬å€æŽã¯èµ·ããªãæ°ãããããæãåçŽãªäŸããå§ããŠããšèšã£ãŠããéããå€åæåã¯ã·ã³ãã«ãªäŸã§èŠãŠããã®ãè¯ãããšããããšããšæããããããã¯ãã®éãã ãšæãã
State update functions
äžå€ã®ç¶æ ãæŽæ°ããæãäžè¬çãªæ¹æ³ã®1ã€ã¯ãããçš®ã®ç¶æ æŽæ°é¢æ°ã䜿çšããããšã§ããã§Reduxã®ã§ã¯ãããã¯reducerã§ããããããŠäœ¿çšããŠé¡äŒŒã®æ§ç¯ç©ãååšãããããã¯ã®ç¶æ 管çã®ããã®ãã¿ãŒã³ãæŽæ°é¢æ°ãååšããå Žåã¯åžžã«ãå ¥åãåãåããããžãã¹ããžãã¯ãå®è¡ããå ¥åãšå€ãç¶æ ã«åºã¥ããŠæ°ããç¶æ ãåºåãã圹å²ãæãããŸãã
æãåçŽãªäŸããå§ããŠãåã«ç޹ä»ããäžå€ã®Employeeã¯ã©ã¹ã®ããã€ãã®å¯èœãªç¶æ æŽæ°é¢æ°ãèŠãŠã¿ãŸãããããããã®é¢æ°ã¯Employeeã¯ã©ã¹ã®äžéšã§ã¯ãªãããšã«æ³šæããŠãã ããã
class Employee {
final int id;
final String name;
const Employee(this.id, this.name);
}
Employee updateEmployeeId(Employee oldState, int id) {
return Employee(id, oldState.name);
}
Employee updateEmployeeName(Employee oldState, String name) {
return Employee(oldState.id, name);
}
ãã®ãã¿ãŒã³ã¯ç°¡åã§ããµããŒããããŠããæŽæ°ã®ã¿ãå®è¡ãããããã«ããã®ã«åœ¹ç«ã¡ãŸãã
åºæ¬çã«ãå颿°ã¯åã®åŸæ¥å¡ã®ç¶æ ãžã®åç §ãååŸãããããšæ°ããããŒã¿ã䜿çšããŠãŸã£ããæ°ããã€ã³ã¹ã¿ã³ã¹ãæ§ç¯ãããããåŒã³åºãå ã«è¿ããŸãã
åçŽãªå€æ°ã®æŽæ°ãå®è¡ããããã®å®åã³ãŒããå€ãããã«æãããå ŽåããããŸããããã«ãããå¯å€æŠç¥ã«æ»ããããšæãå ŽåããããŸãã
äžå€ããŒã¿ã®å©ç¹ã«åãçµãã§ããå Žåã¯ãããã€ãã®è¿œå ã«æ £ããå¿ èŠããããŸãã
ãã®ã¢ãããŒãã®ãã1ã€ã®æ¬ ç¹ã¯ããªãã¡ã¯ã¿ãªã³ã°ãå°é£ã«ãªãããšã§ããEmployeeã®ããããã£ã®ããããã远å ãåé€ããŸãã¯å€æŽããå Žåãå€ãã®ããçŽããå¿ èŠã«ãªãå¯èœæ§ããããŸãã
æŽæ°é¢æ°ã¯éåžžãã³ãŒãããŒã¹ã®å®å šã«ç°ãªãéšåã§èšè¿°ãããããããã®ã¢ãããŒãã§ã¯ããžãã¹ããžãã¯ãããŒã¿ããåé¢ããåŸåããããŸããäžéšã®ãããžã§ã¯ãã§ã¯ãããã倧ããªå©ç¹ã«ãªãå¯èœæ§ããããŸãã
State update class methods
ãç¶æ ããšãç¶æ æäœã«é¢é£ãããã¹ãŠãããã£ããã«ä¿æãããå Žåã¯ãåå¥ã®ãããã¬ãã«é¢æ°ã®ä»£ããã«ã¯ã©ã¹ã®ã¡ãœããã䜿çšã§ããŸãã
class Employee {
final int id;
final String name;
const Employee(this.id, this.name);
Employee updateId(int id) {
return Employee(id, name);
}
Employee updateName(String name) {
return Employee(id, name);
}
}
ãã®ã¢ãããŒãã§ã¯ãåæŽæ°ã¡ãœãããEmployeeã¯ã©ã¹ã«å±ããŠããããšãæããã§ãããããååã®åé·æ§ãæžããããšãã§ããŸãããŸããçŸåšã®ã€ã³ã¹ã¿ã³ã¹ãå€ãç¶æ
ã§ãããšæ³å®ãããŠãããããå€ãç¶æ
ãæç€ºçã«æž¡ãå¿
èŠããªããªããŸãããé©åãªã³ãŒãã®è²ä»ãããªããšãäž¡æ¹ã®æŽæ°ã¡ãœãããåãã³ãŒããæã£ãŠããããã«èŠãããããããŸããããupdateId()
ã¯ãåãåã£ãåŒæ°idãšå€ãnameã䜿çšããŠEmployeeã®æ°ããã€ã³ã¹ã¿ã³ã¹ãäœæããŠããŸããupdateName()
ã¡ãœããã¯éã®ããšãããŠããŸãã
ãã®æ¹æ³ã§è¡ãããšã®æ¬ ç¹ã¯ãå€ãæŽæ°ããããã®ããžãã¯ãããçšåºŠåºå®ãããŠãããç¶æ ã¯ã©ã¹ã«çŽæ¥é¢é£ä»ããããŠããããšã§ããããã¯ãå Žåã«ãã£ãŠã¯æ£ç¢ºã«å¿ èŠãªããšãããããŸããããã©ã¡ãã®æ¹æ³ã§ãåé¡ã«ãªããªãå ŽåããããŸãã
ãã¹ãŠããŸã£ããã«ä¿ã€ïŒé¢å¿ã®åé¢ã¯ãã»ãšãã©ã®ããã®éçºè ãç±å¿ã«æ¯æããŠããããšã§ãããããŒãºãæ éã«æ€èšããå¿ èŠããããŸããäžè¬çã«èšã£ãŠãæžå¿µäºé ãåé¢ããã°ããã»ã©ãã¢ãŒããã¯ãã£ã¯æè»ã«ãªããŸãããåé¢ãããããšçµç¹ã®èª²é¡ãçããå¯èœæ§ããããŸãã
äžå€ã¯ã©ã¹ã®ãã¹ãŠã®ããããã£ã®æŽæ°ã¡ãœãããäœæãããšãé¢åã«ãªãå¯èœæ§ããããŸããæ¬¡ã«ããã®æ©èœã1ã€ã®ã¡ãœããã«çµ±åããæ¹æ³ãèŠãŠãããŸãã
Copy methods
äžå€ã®ããŒã¿ã䜿çšããDartããã³Flutterãããžã§ã¯ãã§äœ¿çšãããäžè¬çãªãã¿ãŒã³ã¯ãã¯ã©ã¹ã«copyWith()ã¡ãœããã远å ããããšã§ããããã¯ããªãã䜿çšããŠããã©ããªæŠç¥ãããåçŽã§ããåäžã«ããããšãã§ããŸãïŒ
class Employee {
final int id;
final String name;
const Employee(this.id, this.name);
Employee copyWith({int id, String name}) {
return Employee(
id ?? this.id,
name ?? this.name,
);
}
}
ãã®copyWith()
ã¡ãœããã¯éåžžãããã©ã«ããªãã§ååä»ããªãã·ã§ã³ãã©ã¡ãŒã¿ã䜿çšããå¿
èŠããããŸãããã®return
ã¹ããŒãã¡ã³ãã¯ãDartã®if nullæŒç®å??ãã䜿çšããŠãåŸæ¥å¡ã®ã³ããŒãåããããã£ã®æ°ããå€ãååŸããããæ¢åã®ç¶æ
ã®å€ãä¿æããããæ±ºå®ããŸããã¡ãœãããidã®å€ãåãåã£ãå Žåããã®å€ãnull
ã§ãªããã°ããã®å€ãã³ããŒã§äœ¿çšãããŸããååšããªãããæç€ºçã«ã«nullã«èšå®ãããŠããå Žåã¯ã代ããã«this.idã䜿çšãããŸããcopyã¡ãœããã¯æè»æ§ãããã1åã®åŒã³åºãã§ä»»æã®æ°ã®ããããã£ãæŽæ°ã§ããŸãã
copyWith()ã䜿ã£ããµã³ãã«ã§ãã
final emp1 = Employee(1, "Bob");
final emp2 = emp1.copyWith(id: 3);
final emp3 = emp1.copyWith(name: "Jim");
final emp4 = emp1.copyWith(id: 3, name: "Jim");
ãã®ã³ãŒããå®è¡ããããšãemp2
倿°ã¯emp1
æŽæ°ãããid
å€ã§ã®ã³ããŒãåç
§ããŸãããname
倿ŽãããŸãããemp3
ã³ããŒã«ã¯ãæ°ããååãšãå
ã®IDãæã€ããšã«ãªããŸãããã®Employeeã¯ã©ã¹ã§ã¯ãemp4
ã³ããŒæäœã¯ãã¹ãŠã®å€ã眮ãæãããããæ°ãããªããžã§ã¯ããäœæããã®ãšãŸã£ããåãã§ãã
ç¶æ
æŽæ°é¢æ°ãŸãã¯ã¡ãœããã¯ãcopyWith()ã
ã¿ã¹ã¯ãå®è¡ããããã«å©çšã§ããŸããããã«ãããã³ãŒãã倧å¹
ã«ç°¡çŽ åã§ããŸãã
Employee updateEmployeeId(Employee oldState, int id) {
return oldState.copyWith(id: id);
}
Employee updateEmployeeName(Employee oldState, String name) {
return oldState.copyWith(name: name);
}
ããã§ã®ç¶æ
æŽæ°é¢æ°ã®äœ¿çšã¯ããžã®åŒã³åºãã®éåžžã«èãã©ãããŒã«ãªã£ãŠãããããããéãã ãšèããããšãã§ããŸãcopyWith()
ãå€ãã®å Žåãå
ã®ãªããžã§ã¯ãã®ããŒã¿ãç Žæããæ¹æ³ããªããããå€éšã³ãŒããã³ããŒæ©èœãçŽæ¥äœ¿çšã§ããããã«ããããšã¯åé¡ãããŸããã
äžå€ã¯ã©ã¹ã®ããããã£ãäžå€ã¯ã©ã¹ã§ããå ŽåãcopyWith()
ãã¹ããããããããã£ãæŽæ°ããããã«åŒã³åºãããã¹ãããå¿
èŠãããå ŽåããããŸããæ¬¡ã«ããã®ã·ããªãªã«ã€ããŠèª¬æããŸãã
Updating complex properties
1ã€ä»¥äžã®ããããã£ãäžå€ãªããžã§ã¯ãã§ãããå Žåã¯ã©ããªããŸããïŒãããã®æŽæ°ãã¿ãŒã³ã¯ãããªãŒå šäœã§æ©èœããŸãã
class EmployeeName {
final String first;
final String last;
const EmployeeName({this.first, this.last});
EmployeeName copyWith({String first, String last}) {
return EmployeeName(
first: first ?? this.first,
last: last ?? this.last,
);
}
}
class Employee {
final int id;
final EmployeeName name;
const Employee(this.id, this.name);
Employee copyWith({int id, EmployeeName name}) {
return Employee(
id: id ?? this.id,
name: name ?? this.name,
);
}
}
çŸåšãEmployeeã«ã¯ã¿ã€ãEmployeeNameã®ããããã£ãå«ãŸããŠãããäž¡æ¹ã®ã¯ã©ã¹ã¯äžå€ã§ãããcopyWith()
æŽæ°ã容æã«ããã¡ãœãããåããŠããŸãããã®èšå®ã§ã¯ãåŸæ¥å¡ã®å§ãæŽæ°ããå¿
èŠãããå Žåã¯ã次ã®ããã«ããããšãã§ããŸãã
final updatedEmp = oldEmp.copyWith(
name: oldEmp.name.copyWith(last: "Smith"),
);
ã芧ã®ãšãããåŸæ¥å¡ã®å§ãæŽæ°ããã«ã¯ãäž¡æ¹ã®ããŒãžã§ã³ã®copyWith()
ãäžç·ã«äœ¿çšããå¿
èŠããããŸãã
Updating collections
äžå€ã®ã³ã¬ã¯ã·ã§ã³ãæŽæ°ããããã«äœ¿çšãããã¿ãŒã³ã¯ãã³ã¬ã¯ã·ã§ã³ã®èšå®æ¹æ³ãšãäžå€ã®çŽç²äž»çŸ©è ã®çšåºŠã®äž¡æ¹ã«ãã£ãŠç°ãªããŸãã
æŽæ°ãã¿ãŒã³ã«çŠç¹ãåœãŠãè°è«ãç¶ããããã«ãéçŸå®çã«åçŽåãããããŒã¿ã¯ã©ã¹ã䜿çšããŸãã
class NumberList {
final List<int> _numbers;
List<int> get numbers => List.unmodifiable(_numbers);
NumberList(this._numbers);
}
ãã®ã¯ã©ã¹ã¯æè¡çã«ã¯å¯å€(mutable)ãªãªã¹ããæããŠããŸããã(ã¯ã©ã¹)å€éšã«ã¯unmodifiableãªã³ããŒã®ã¿ãæäŸããŸãããã®ãªã¹ããä¿®æ£ããããã®ç¶æ æŽæ°é¢æ°ãšããŠã
NumberList addNumber(NumberList oldState, int number) {
final list = oldState.numbers.toList();
return NumberList(list..add(number));
}
class Number{ int n; //finalãç¡ããšã³ããŒå ãä¿®æ£ãããŠããŸãã //(List.unmodifiableãã·ã£ããŒã³ããŒãè¿ããã) //âfinalãä»ããã°ä¿®æ£ã§ããªãã Number(this.n); } class NumberList { final List<Number> _numbers; List<Number> get numbers => List.unmodifiable(_numbers); NumberList(this._numbers); } main() { NumberList addNumber(NumberList oldState, Number number) { final list = oldState.numbers.toList(); return NumberList(list..add(number)); } NumberList numList=NumberList([Number(1),Number(2),Number(3),]); var newList=addNumber(numList,Number(10)); newList.numbers[0].n=100; print(numList.numbers[0].n); //100 print(newList.numbers[0].n); //100 }
ãã®ã¢ãããŒãã¯å¹ççã§ã¯ãããŸããã
oldState.numbers
ã¯ãoldStateã®ãªã¹ãã®ã³ããŒãè¿ããŸãããããããã¯unmodifiableã§ãã
ã§ããããtoList()ã¡ãœããã䜿ã£ãŠmutableãªå¥ã®ãªã¹ããçæããŠããŸãã
ãããŠæ°ããNumberListã€ã³ã¹ã¿ã³ã¹ãçæããŠããŸãããã®ã³ã³ã¹ãã©ã¯ã¿ã«ãæ°ããæ°å€ã远å ããã³ããŒãªã¹ããæž¡ããŠNumberListã€ã³ã¹ã¿ã³ã¹ãçæããŠããŸãã
Dartã®ã«ã¹ã±ãŒãæŒç®åã䜿çšããŠãã³ã³ã¹ãã©ã¯ã¿ã«æž¡ãããåã«èŠçŽ ã®è¿œå ãè¡ã£ãŠããŸãã
å¥ã®æŽæ°ã¡ãœãããšããŠã
class NumberList {
final List<int> _numbers;
List<int> get numbers => List.unmodifiable(_numbers);
NumberList(this._numbers);
NumberList add(int number) {
return NumberList(_numbers..add(number));
}
}
ãã®æŽæ°ã¡ãœããã¯è¯ããã€ã³ãããããŸããåé·æ§ãå°ãªããã³ãŒãéãå°ãªããªããŸãã
泚æãã¹ã埮åŠãªç¹ã®1ã€ã¯ã_numbersã倿ŽããŠåå©çšããŠããããšã§ããããã¯å éšã³ãŒãå ããã®ã¿å¯èœã§ããããããã®ã¢ãããŒãã«ã¯æºè¶³ã§ãããããããŸããããåçæ§ã®æ¯èŒã«é¢ããŠæœåšçãªå¯äœçšããããŸãã
ããã€ãã®ç¶æ 管çãã¿ãŒã³ã¯ç¶æ ã®streamãçæããŸããæ°ããç¶æ ãçæããã(ç¶æ ãæŽæ°ããã)åºŠã«æ¯åãstreamã®çµæãšããŠæ°ããç¶æ ã€ã³ã¹ã¿ã³ã¹ãçºããããUIã³ãŒãã«å±ããããŸãã
å¹çåãæå€§åãããããå€ãç¶æ ãæ°ããç¶æ ãšç°ãªããã調ã¹ãå¿ èŠããããããããŸãããäžèšã®add()ã¡ãœããã¯NumberListåã®æ°ããã€ã³ã¹ã¿ã³ã¹ãçæããŸããã_numbersã€ã³ã¹ã¿ã³ã¹ã¯å ±éã®ãã®ã䜿ã£ãŠããç¶æ³ã§ãã
æ°ããç¶æ ãšå€ãç¶æ ã®æ¯èŒã®å®è£ ã«ãã£ãŠã¯ãç¶æ ã¯å šãå€ãã£ãŠããªãããšããééã£ãçµæããããããããããŸããã
(add()ã¡ãœãããè¿ãå€ã®_numbersãã£ãŒã«ãããå ã®NumberListã€ã³ã¹ã¿ã³ã¹ã®_numbersãã£ãŒã«ããåããã®ã ããã)
ãšããããšã§ã倿Žã®ãã³ã«ãªã¹ããåäœæããããšã奜ã人ãããŸãã
class NumberList {
final List<int> _numbers;
List<int> get numbers => List.unmodifiable(_numbers);
NumberList(this._numbers);
NumberList add(int number) {
return NumberList(_numbers.toList()..add(number));
}
}
toList()ã¡ãœããã®åŒã³åºãã远å ããããšã§ããæŽæ°åŸã®ãªã¹ãããšããŠã®æ°ããã€ã³ã¹ã¿ã³ã¹(_numbersã®ã·ã£ããŒã³ããŒ*ã«æ°ããèŠçŽ ã远å ããã€ã³ã¹ã¿ã³ã¹)ãæããNumberListã€ã³ã¹ã¿ã³ã¹ãçæãããŠ(addã¡ãœããã®è¿ãå€ãšããŠ)è¿ãããããã«ãªãã®ã§ãåé¡ã解決ããŸããã
(* :ã·ã£ããŒã³ããŒã ããã®ã±ãŒã¹ã§ã¯ãªã¹ãã®èŠçŽ ãããªããã£ãå(intå)ãªã®ã§ãã·ã£ããŒã³ããŒã§ãåé¡ã«ãªããªãã)
Conclusion
ãªããžã§ã¯ããšã³ã¬ã¯ã·ã§ã³ã®äžå€æ§ãåŠçããæ¹æ³ã¯ãããããããŸãããè€éãªããŒã¿ã§ãæ±ãéã«ãäºæããå€åããªãããã«ããæ¹æ³ã®ããã€ãã«ç²ŸéããŠããå¿ èŠããããŸãã
ããã§ã¯ã³ãŒããžã§ãã¬ãŒã·ã§ã³ã«ããimmutablityã®å®çŸã«é¢ããŠã¯è§ŠããŸãããããããã®æ¹æ³ãçšãããšèªåã§ã³ãŒããã¿ã€ãã³ã°ããéãæžãããã§ãããããããã®æ å ±ãå¿ èŠãªå Žåbuild_valueãªã©ã®Dartããã±ãŒãžãã芧ãã ããã
åè
https://dart.academy/immutable-data-patterns-in-dart-and-flutter/#