singleton with thread-safe
// swift, "let" will call swift_dispatch_once, so it is thread-safe
class Singleton {
private init() { }
static let shared = Singleton()
}
// The lazy initializer for a global variable (also for static members of structs and enums)
// is run the first time that global is accessed,
// and is launched as dispatch_once to make sure that the initialization is atomic.
// This enables a cool way to use dispatch_once in your code:
// just declare a global variable with an initializer and mark it private.
init sequence
⼀般来说,⼦类的初始化顺序是:
- 设置⼦类⾃⼰需要初始化的参数, power = 10
- 调⽤⽗类的相应的初始化⽅法, super.init()
- 对⽗类中的需要改变的成员进⾏设定, name = "tiger"
Designated,Convenience 和 Required
所以 Swift 有了超级严格的初始化⽅法。⼀⽅⾯,Swift 强化了 designated 初始化⽅法的地位。
Swift 中不加修饰的 init ⽅法都需要在⽅法中保证所有⾮ Optional 的实例变量被赋值初始化,⽽在
⼦类中也强制 (显式或者隐式地) 调⽤ super 版本的 designated 初始化,所以⽆论如何⾛何种路
径,被初始化的对象总是可以完成完整的初始化的。
与 designated 初始化⽅法对应的是在 init 前加上 convenience 关键字的初始化⽅法。这类⽅法
是 Swift 初始化⽅法中的 “⼆等公⺠”,只作为补充和提供使⽤上的⽅便。
所有的 convenience 初始化⽅法都必须调⽤同⼀个类中的 designated 初始化完成设置,
另外 convenience 的初始化⽅法是不能被⼦类重写或者是从⼦类中以 super 的⽅式被调⽤的。
初始化⽅法永远遵循以下两个原则:
1.必须保证对象完全初始化,这可以通过调⽤本类型的 designated 初始化⽅法来得到保证;
2.⼦类的 designated 初始化⽅法必须调⽤⽗类的 designated ⽅法,以保证⽗类也完成初始
化。
对于某些我们希望⼦类中⼀定实现的 designated 初始化⽅法,我们可以通过添加 required 关键
字进⾏限制,强制⼦类对这个⽅法重写实现。
这样做的最⼤的好处是可以保证依赖于某个designated 初始化⽅法的 convenience ⼀直可以被使⽤。
class ClassA {
let numA: Int
init(num: Int) {
numA = num
}
convenience init(bigNum: Bool) {
self.init(num: bigNum ? 10000 : 1)
}
}
class ClassB: ClassA {
let numB: Int
override init(num: Int) {
numB = num + 1
super.init(num: num)
}
}
只要在⼦类中实现重写了⽗类 convenience ⽅法所需要的 init ⽅法的话,我们在⼦类中就也可以
使⽤⽗类的 convenience 初始化⽅法了。⽐如在上⾯的代码中,我们在 ClassB ⾥实现了 init(num:
Int) 的重写。这样,即使在 ClassB 中没有 bigNum 版本的 convenience init(bigNum: Bool) ,我们仍
然还是可以⽤这个⽅法来完成⼦类初始化:
let anObj = ClassB(bigNum: true)
// anObj.numA = 10000, anObj.numB = 10001
Failures init, init can return nil
class MyClass {
init?(dict: Dictionary<Int, Int>) {
return nil
}
}
lazy variable and lazy methods
class MyClass {
lazy var num: Int! = {
let number = 10
return number
}()
}
let aClass = MyClass()
print(aClass.num) //10
aClass.num = 11
print(aClasss.num) // 11
aClass.num = nil // re init of num
print(aClass.num) // 10