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
のように明示的に呼ぶ必要はありません。