https://developer.apple.com/swift/ より
The Swift Programming Language (iBooks Store)をざっくり目を通してつらつらと。
初期化処理
イニシャライザ (Initializer)
Swiftに関するメモ その4 - 継承でも触れましたが、init というメソッドを定義することによって、クラスや構造体のインスタンスが生成される (初期化される) 際に呼ばれる処理を実装することができます。
class SomeClass {
var someValue: Int
init() {
someValue = 2
}
}
let aClass = SomeClass() // aClass.someValue は 2
プロパティの初期値
プロパティの宣言時に初期値を設定することで、init メソッドを使わなくても初期値を決めることができます。
class SomeClass {
var someValue: Int = 2
}
let aClass = SomeClass() // aClass.someValue は 2
init メソッドでのプロパティの値を設定すると、プロパティの初期値を上書きするような動作になります。
したがって、
class SomeClass {
init() {
someValue = 1
}
var someValue: Int = 2
}
let aClass = SomeClass() // aClass.someValue は 1
のようになります。ただ、このサンプルは悪い書き方の例です。
コードの読みやすさの面でもプロパティの宣言は init より前に記述した方が無難だと思います。
クロージャを使ったプロパティの初期値
プロパティの初期値には定数だけでなく、関数を指定することもできます。
class Fibonacci10 {
let values: Int[] = {
var array = [0, 1];
for n in 2...9 {
array += array[n - 2] + array[n - 1]
}
return array;
}()
}
let fibonacci = Fibonacci10() // fibonacci.values = [0,1,1,2,3,5,8,13,21,34]
この例の場合、values に指定されたクロージャが実行され、その戻り値が初期値として代入されます。
init メソッドの引数
init メソッドは引数を取ることができます。
class SomeClass {
var someValue: Int = 2
init(value:Int) {
someValue = value
}
}
let aClass = SomeClass(value:3) // aClass.someValue は 3
value というインスタンスの初期化に必要なパラメータを設定します。
この時、init メソッドのパラメータ value は引数の名前として指定する必要があります。
class SomeClass {
var someValue: Int = 2
init(value:Int) {
someValue = value
}
}
let aClass = SomeClass(3) // エラー!!!
もし引数が自明で名前は必要ないという場合は _ を利用します。
class SomeClass {
var someValue: Int = 2
init(_ value:Int) {
someValue = value
}
}
let aClass = SomeClass(3) // aClass.someValue は 3
定数の初期化
定数なプロパティも init メソッドでは初期値の置き換えが可能です。
class SomeClass {
let someValue: Int = 2
init(value:Int) {
someValue = value
}
}
let aClass = SomeClass(value:3) // aClass.someValue は 3
構造体の init メソッドの省略
構造体では init メソッドを省略して、プロパティの名前で引数を渡すことによってプロパティの初期化ができます。
struct SomeStructure {
let someValue: Int
}
let aStruct = SomeStructure(someValue:2) // aStruct.someValue は 2
というコードは
struct SomeStructure {
let someValue: Int
init(someValue:Int) {
self.someValue = someValue
}
}
let aStruct = SomeStructure(someValue:2) // aStruct.someValue は 2
と同義です。
複数の init メソッド
引数の異なる複数の init メソッドを定義することができます。
struct SomeStructure {
let someValue: Int
init() {
someValue = 1
}
init(value:Int) {
someValue = value
}
}
let aStruct = SomeStructure() // aStruct.someValue は 1
let anotherStruct = SomeStructure(value:2) // anotherStruct.someValue は 2
convenience な init メソッド
クラスでも複数の init メソッドを定義できます。
その際、必ず実行される init メソッドと利便性のために補助的に利用される init メソッドを定義することができます。
class SomeClass {
let someValue:Int
init(value:Int) {
someValue = value
}
convenience init(stringValue:String) {
self.init(value:stringValue.toInt()!);
}
}
convenience に指定された init メソッドからは必ず「指定された (Designated)」init メソッドを呼ぶ必要があります。
Designated init の概念は継承したクラスにも適用されます。ベースクラスに Designated な init メソッドがある場合には、それらが super.init で呼ばれる必要があります。
終了処理 (deinit)
Objective-C でいうところの dealloc と同じようにインスタンスが破棄されるタイミングで呼ばれる deinit を定義することができます。
deinit は引数をとることができず、また継承したクラスでもベースクラスの deinit は自動的に呼ばれるため、super.deinit のように明示的に呼ぶ必要はありません。