SwiftのArrayがミュータブルでもCovariantな理由

SwiftのArrayでは次のようなことができます。

```swift:(A)
class Animal {}
class Cat: Animal {}

var cats: Array<Cat> = [Cat(), Cat()]
var animals: Array<Animal> = cats

// 実体はCatのArrayのはずなのにAnimalを格納できる！？
animals[0] = Animal()
```

これを見ると型安全性がぶっ壊れてるんじゃないかと思ってしまいますが、そうではありません。SwiftのArrayにとってこれは安全な挙動です。

Covariantなコレクション
---------------------

__(A)__ のように、 _Cat_ が _Animal_ の派生型なら _Array\<Cat\>_ も _Array\<Animal\>_ の派生型となるとき、 _Array_ は __Covariant（共変）__ であると言います<sub>\[<a href="#1" name="-1">\*1</a>\]</sub>。

_Array\<Cat\>_ に _Animal_ オブジェクトが格納できてしまうように、ミュータブルなコレクションがCovariantだとそのコレクションに本来格納できない型の要素が格納できることになり、型安全ではありません<sub>\[<a href="#2" name="-2">\*2</a>\]</sub>。そのため、ミュータブルなコレクションはCovariantとして宣言できません。（普通は __Invariant（不変）__ として宣言されます。）

一方で、 __イミュータブルなコレクションはCovariantであっても問題ありません__ 。要素が変更されないのであれば、 _Array\<Cat\>_ は _Array\<Animal\>_ として安全に振る舞うことができるからです。

```swift:(B)
var cats: Array<Cat> = [Cat(), Cat()]
var animals: Array<Animal> = cats

// 要素が変更されないなら何も問題なし
for animal: Animal in animals {
	println(animal)
}
```

実際に、C#やScala、Ceylonなどの言語では、イミュータブルなコレクションがCovariantとして宣言されています。

SwiftのArrayがミュータブルでもCovariantなのはなぜか
---------------------------------------------

__SwiftのArrayはクラスではなく構造体です。そして、構造体は値型です。__

論理的には、 __値型はイミュータブルなクラスと等価__ と考えられます。次のコードの _Int_ は、値型と考えてもイミュータブルなクラスと考えても問題ありません<sub>\[<a href="#3" name="-3">\*3</a>\]</sub>。

```swift:(C)
var a: Int = 123
a = a + 1
```

_Int_ が値型だと考えてみましょう。 _a + 1_ を実行しても _123_ という数そのものが変更されたわけではなく、 _123_ に _1_ を足した _124_ という新たな値が _a_ に代入されるだけです。 _123_ は _123_ であり、 _123_ が _124_ になったわけではありません。

これは、 _Int_ がイミュータブルなクラスだとして次のように考えた場合と等価です。 _123_ というオブジェクトに _1_ を足した結果の新たな _124_ というオブジェクトを生成し、それを _a_ に代入した、と。

よって、

- イミュータブルなコレクションはCovariantでも型安全
- 値型はイミュータブルなクラスと等価
- SwiftのArrayは値型

から、 __SwiftのArrayはCovariantでも型安全__ と言えます。

### 値型は本当にイミュータブルなクラスと等価か

ちょっと待って下さい！次の例を見て下さい。

```swift:(D)
struct Fraction { // 分数
	var numerator: Int // 分子
	var denominator: Int // 分母
}

var fraction = Fraction(numerator: 1, denominator: 3)
fraction.numerator = 2 // 値そのものを変更できた！
```

値型はイミュータブルなクラスと等価だと書きましたが、fractionに代入された値そのものが変更されています。これはどう考えれば良いでしょうか？

Fractionをイミュータブルなクラスとしたときに、対応するコードは次のようになります。

```swift:(E)
class Fraction { // 分数
	let numerator: Int // 分子
	let denominator: Int // 分母
	init(numerator: Int, denominator: Int) {
		self.numerator = numerator
		self.denominator = denominator
	}
}

var fraction = Fraction(numerator: 1, denominator: 3)
fraction = Fraction(numerator: 2, denominator: fraction.denominator)
```

このように、構造体のメンバを書き換える操作は、イミュータブルなオブジェクトを対応するメンバだけ変えて再生成することに対応します。

この二つが等価なことは、次の二つを比較するとよくわかります。

```swift:(D':structの場合)
var a = Fraction(numerator: 1, denominator: 3)
var b = a
a.numerator = 2 // a == 2/3, b == 1/3
```

```swift:(E':classの場合)
var a = Fraction(numerator: 1, denominator: 3)
var b = a
a = Fraction(numerator: 2, denominator: a.denominator) // a == 2/3, b == 1/3
```

つまり、

```swift:(A)の抜粋
animals[0] = Animal()
```

のコードは意味的には次のようなものなのです。

```swift:(F)
// animalsをコピーして0番目の要素をAnimal()に変えたArrayを再生成
animals = replace(animals, 0, Animal())
```

_Array_ を変更しているように見えても実際には新しい値を生成しているのと同じだから、 _Array_ はイミュータブルな型だと考えることができ、Covariantでも安全なのです。

### もっと簡単な考え方

_Array_ は値型なので

```swift:(A)の抜粋
var animals: Array<Animal> = cats
```

の時点で _Array_ 全体がコピーされます。 _animals_ は _cats_ から要素をコピーされた新しい _Array\<Animal\>_ なので、その後 _Animal_ オブジェクトが格納されようと _cats_ には関係ありません。

### Arrayを代入したり要素を変更する度にコピーしたらパフォーマンスが悪いのでは？

実際には、要素を変更する度に _Array_ がコピーされるわけではありません。コピーしないと安全性が保てない場合にだけコピーされます。

["SwiftのArrayが実はすばらしかった"](http://qiita.com/koher/items/47f444200d4e02b6414e)で、コピーが頻発しているように見えてもパフォーマンスが悪化しない理由を説明しています。（要素の変更については書いていませんが同じように考えられます。）

まとめ
-----

次の理由から、 __SwiftのArrayはミュータブルでCovariantでも型安全__ です。

- イミュータブルなコレクションはCovariantでも型安全
- 値型はイミュータブルなクラスと等価
- SwiftのArrayは値型

---------------------------------------------------------------

\[<a href="#-1" name="1">\*1</a>\] 逆に、 _B_ が _A_ の派生型のときに _Foo\<A\>_ が _Foo\<B\>_ の派生型として扱えるとき、 _Foo_ は __Contravariant（反変）__ であると言います。

\[<a href="#-2" name="2">\*2</a>\] 実際にはコレクションに限らずジェネリックな型で一般的に起こることだし、要素を追加しなくても _Array#search(Element)_ のようなメソッドもアウトですが、ややこしくなるだけなので話を限定して進めます。

\[<a href="#-3" name="3">\*3</a>\] 実際、Scalaの _Int_ はイミュータブルなクラスですが、処理系では値型（プリミティブ型）であるJavaの _int_ と等価なものとして扱われ、高速に計算されます。