Heart Of Swiftを理解する(第1章)
概要
本スクラップはHeart Of Swiftの内容を自分自身が理解するために、文章にまとめたものを記述していきます。
そのため自分の理解が誤っている可能性があります。
Value Semanticsとは
SwiftにおけるValue Semantics
SwiftにおけるValue Semanticsとは、インスタンスを初期化、代入、引数として渡すなどしても、元の値のコピーが作成され、そのコピーと元の値は独立して変更することができる。つまり、どちらを変更してももう一方に影響を与えない 性質を持つもののことを指しています。
Value Semantics
前述したようにValue Semanticsは、変更に対して他方に影響を与えない型です。
例えば以下のようなコードは自身以外に影響を与えません。
struct Foo {
var value: Int = 0
}
var a = Foo()
var b = a
a.value = 2 // この時b.valueは`2`に変更されません。
理由としては、Fooは 値型 であるためです。
値型のインスタンス(より具体的に言うと、インスタンスを表すバイト列)は変数に直接格納されます。
そしてそのインスタンスを変数に代入した際、そのバイト列をコピーしてから変数に書き込まれます。
aとbは互いに変更に影響を与えないので、Foo
はValue Semanticsを持っていると言えます。
Reference Semantics
Value Semanticsの対比として、Reference Semanticsという性質もあります。
Reference Semanticsは変更が他方にも影響してしまうような性質を持つものを指しています。
例えば以下のようなコードは、変更が他方にも影響してしまいます。
class Foo {
var value: Int = 0
}
var a = Foo()
var b = a
a.value = 2 // この時b.valueも`2`に変更されてしまいます。
理由としては、Fooは 参照型 であるためです。
値型と異なり参照型は、インスタンスを変数に代入してもバイト列は格納されません。
インスタンスを表すバイト列は別の領域に保存され、変数にはその保存領域を表すアドレス(e.g. 0x123DEF etc.)が保存されます。
Value Semanticsと値型 / Reference Semanticsと参照型はそれぞれイコールではない
注意しなければならないのは、値型ならValue Semanticsを持つ、参照型ならReference Semanticsを持つとは限りません。
値型でもValue Semanticsを持たない場合や、参照型でもValue Semanticsを持つ場合もあります。
値型でもValue Semanticsを持たない場合
class Bar {
var value: Int = 0
}
struct Foo {
var value: Int = 0
var bar: Bar = Bar()
}
var a = Foo()
var b = a
a.value = 2
a.bar.value = 3 // この時b.bar.valueも変更されてしまう。
このようにFoo
は値型であるが、独立しておらず変更が他方にも影響してしまっています。
つまりFoo
はValue Semanticsを持たないと言えます。
参照型でもValue Semanticsを持つ場合
class Foo {
let value: Int = 0
}
var a = Foo()
var b = a
a.value = 100 // これはコンパイルエラー
参照型はあるがvalue
プロパティはイミュータブルであるので変更されることがなく、そのため他方に影響を与えることもありません。つまりFoo
はValue Semanticsを持つと言えます。
また先程の値型でもValue Semanticsを持たない場合の例のBar
を以下のように書き換えると、
class Bar {
let value: Int = 0
}
struct Foo {
var value: Int = 0
var bar: Bar = Bar()
}
var a = Foo()
var b = a
a.value = 2
a.bar.value = 3 // コンパイルエラー
a.bar.value
は書き換えることはできないので、他方に影響を与える可能性がなくなります。
よってこの場合、Foo
はValue Semanticsを持つと言えます。
Value SemanticsかReference Semanticsかの判断
ここまで値型だが参照型のミュータブルなプロパティを持っていればValue Semanticsを持たない、という例がありましたが、「値型だが参照型のミュータブルなプロパティを持っていればValue Semanticsを持たない」とパターンで判断するのは危険です。
値型だが参照型のミュータブルなプロパティを持っていても、Copy-on-Writeなどの仕組みを使ってValue Semanticsを持つ場合もあるみたいです。(Array
など)
Value Semanticsを持つかどうかは、定義に基づいているかどうかで判断することが重要です。