訂正:swiftの仕様変更に伴い、ArrayとDictionaryの挙動に対する説明を改めました(2014/7/9)。
Dictionary型とArray型の代入とコピー
Dictionary型とArray型ともに値型であるために、変数や定数に代入するとき、あるいは関数の引数や返り値となったときには同じような挙動をします。
変数・定数に代入するときや、関数の引数・返り値となったときには、その値がコピーされて渡されます。ただし、キーや値が値型の場合と参照型の場合とで、コピーのされ方が次のように異なります。
- 値型の場合: それらも同様にコピーされる
- 参照型の場合: 値そのものはコピーされず、参照がコピーされる
例として、変数にDictionaryが代入された場合を見てみましょう。
var pacificCountries = ["JPN" : "Japan", "USA" : "America"] var newCountries = pacificCountries newCountries["USA"] = "United States Of America" println(pacificCountries["USA"]) // "America"
newCountriesに、Dictionary型であるpacificCountriesの値を代入しています。このとき、newCountriesにはpacificCountriesが値型としてコピーされて渡されるため、newCountriesに変更を行っても、pacificCountriesはその影響を受けていません。
Objective-CのNSDictionaryに関しては値型のような挙動を示さず、同じようなコードを書くと、元の値も変更されてしまいます。
NSMutableDictionary *countries = @{@"JPN" : @"Japan", @"USA" : @"America"}.mutableCopy;
NSMutableDictionary *newCountries = countries;
newCountries[@"USA"] = @"United States Of America";
NSLog(@"%@", countries[@"USA"]); // "United States Of America"
Array型についても、変数・定数に代入した場合や、関数の引数・戻り値になった場合、中の要素がコピーされます。
例として、変数にArrayが代入された場合を見てみましょう。
var animalsFirst = ["dog", "cat", "elephant"] var animalsSecond = animalsFirst animalsFirst[0] = "wolf" println(animalsSecond[0]) // "dog"
DictionaryやArrayを定数として宣言した場合には、その要素の変更も許しません。
let foods = ["tomato", "egg", "fish"] foods[1] = "rice" // エラー let drinks = ["white" : "milk", "yellow" : "beer"] drinks["yellow"] = "applejuice" // エラー
なお、Swiftではコード上はコピーされているように見える値に関しても、実際のコピーは本当に必要な場合のみにしか行われません。最適化のために、コピー実行はすべてSwiftによって管理されます。
