クラスとストラクチャ
Swiftのクラスは、Objective-Cのクラスとほぼ同じ機能でデータ型を定義します。Objective-Cで使用可能だった機能の多くが、Swiftのクラスでも使用可能です。
ストラクチャも、クラスと同様にデータ型を定義する機能です。プロパティやメソッド、イニシャライザの宣言など、クラスにできることの多くがストラクチャでもできます。しかし、ストラクチャは参照型でないなど、本質的にクラスと異なる部分があります。第1回で取り上げたString、Intなどの値型はストラクチャとして扱われます。
公式ドキュメントによれば、データ型としてストラクチャを考慮すべきケースは次のとおりです。
- 型を作る目的が、比較的単純なデータ値のカプセル化である場合
- インスタンスが参照ではなく、コピーされることが期待される場合
- 保持プロパティが、参照ではなくコピーされることが期待される場合
- 他の既存の型のプロパティやメソッドを継承する必要がない場合
プロパティ、メソッド、イニシャライザなどを定義する構文は、クラスとストラクチャの間でほとんど違いはありません。解説の中で言及のない場合は、両者で同じ構文を用いて定義・宣言が可能と思ってください。
2014/7/21に公開された追加仕様では、新しくクラス、ストラクチャの宣言、プロパティ、メソッド等にpublic,internal,privateのアクセス修飾子が付けられるようになりました。こちらは次回以降に解説します。
プロパティ
ここからは、Swiftのクラスとストラクチャのプロパティ、メソッド、継承を説明していきます。まずはプロパティからです。
定数プロパティに対する挙動
Swiftでは、変数としてだけでなく、定数としてプロパティを宣言することができます。さらに、プロパティにはデフォルト値も宣言可能です。次の例はクラスを宣言するものです。宣言しているCustomRangeClassクラスは、Objective-CのNSRangeに類似したモデルになっています。
class CustomRangeClass { let start: Int // 定数としてプロパティを宣言 var length: UInt = 0 // 変数としてプロパティを宣言 init(start: Int, length: UInt) { self.start = start self.length = length } }
クラスのインスタンス化は、次の例の1行目にあるとおり、クラス名(初期値, ……)という構文で行います。また2行目にあるとおり、定数として宣言したプロパティ(以下、定数プロパティ)への再代入は許されません。
var mutableRange = CustomRangeClass(start: 1, length: 2) mutableRange.start = 2 // エラー
今度は、ストラクチャの宣言とインスタンス化です。イニシャライザ(initメソッド)の宣言がないことと、インスタンス化するときに引数としてプロパティの初期値を与えていること以外は、クラスの宣言と同じです。
struct CustomRangeStruct { let start: Int var length: UInt = 0 } var mutableRange = CustomRangeStruct(start: 1, length: 2) // 変数に代入されたストラクチャインスタンス let immutableRange = CustomRangeStruct(start: 0, length: 4) // 定数に代入されたストラクチャインスタンス mutableRange.length = 3 // 変数に代入されたインスタンスの変数プロパティは再代入可能 immutableRange.length = 5 // エラー
もう一つのポイントとして、値型であるストラクチャは定数に代入すると、その影響がプロパティにまで伝播することがあります。上記の例のように、letキーワードにより定数に代入した場合、変数として宣言したプロパティ(変数プロパティ)にも再代入ができません。
上記の例からは、ストラクチャでは、デフォルト値が設定されていないプロパティがある場合でも、イニシャライザが省略可能であることが見てとれますが、その仕組みは後ほど「ライフサイクルの管理」節で解説します。
一方、参照型であるクラスでは、定数に代入された場合でも、変数で宣言したプロパティに代入ができます。
let immutableRange = CustomRangeClass(start: 0, length: 4) // クラスの場合 immutableRange.length = 5 // 定数に対しては変数プロパティに代入可能
インスタンスに値を保持させるために宣言するプロパティを、本記事では保持プロパティ(Stored Property)と呼びます。上記例の中ではCustomRangeClassやCustomRangeStructのstartやlengthプロパティがこれに当たります。保持プロパティはクラスとストラクチャでのみ定義可能で、列挙型には定義できません。