🕶2020/11/17 Immutable Data Patterns in Dart and Flutter要ē‚¹ć¾ćØ悁

 

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/#

ć‚³ćƒ”ćƒ³ćƒˆć‚’ę®‹ć™

ćƒ”ćƒ¼ćƒ«ć‚¢ćƒ‰ćƒ¬ć‚¹ćŒå…¬é–‹ć•ć‚Œć‚‹ć“ćØćÆć‚ć‚Šć¾ć›ć‚“ć€‚ ā€» ćŒä»˜ć„ć¦ć„ć‚‹ę¬„ćÆåæ…須項ē›®ć§ć™