1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class ClassA {
let numA: Int
init(num: Int) {
numA = num
}
convenience init(bigNum: Bool) {
self.init(num: bigNum ? 100 : 1)
}
}
class ClassB: ClassA {
let NumB: Int
override init(num: Int) {
NumB = num + 1
super.init(num: num)
}
}
let bbb = ClassB(bigNum: true)
bbb.NumB //101
bbb.numA //100
Swift 的 init 只可能被调用一次,因此在 init 中我们可以为常量进行赋值,而不会引起任何线程安全的问题
designated
在 Objective-C 中,init 方法是非常不安全的:没有人能保证 init 只被调用一次,也没有人保证在初始化方法调用以后实例的各个变量都完成初始化,甚至如果在初始化里使用属性进行设置的话,还可能会造成各种问题,虽然 Apple 也明确说明了不应该在 init 中使用属性来访问,但是这并不是编译器强制的,因此还是会有很多开发者犯这样的错误。
所以 Swift 有了超级严格的初始化方法。一方面,Swift 强化了 designated 初始化方法的地位。Swift 中不加修饰的 init 方法都需要在方法中保证所有非 Optional 的实例变量被赋值初始化,而在子类中也强制 (显式或者隐式地) 调用 super 版本的 designated 初始化,所以无论如何走何种路径,被初始化的对象总是可以完成完整的初始化的。
required
加上 required
在方法前,是要求子类必须对其实现
required
& convenience
可同时使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class ClassA {
let numA: Int
init(num: Int) {
numA = num
}
required convenience init(bigNum: Bool) {
self.init(num: bigNum ? 100 : 1)
}
}
class ClassB: ClassA {
let NumB: Int
override init(num: Int) {
NumB = num + 1
super.init(num: num)
}
required convenience init(bigNum: Bool) {
self.init(num: bigNum ? 101 : 1)
}
}
let bbb = ClassB(bigNum: true)
bbb.NumB //102
bbb.numA //101
写不写
required
也可以重写init(bigNum:)
,最好写上好理解。 当你在ClassA
写上 ` required convenience init(bigNum: Bool) ` 这里系统不会提示你让你在ClassB
中实现,但是你可以自己copy 来实现也是没问题的
convenience
init 多态方法,在init 前加上 convenience
补充使用,初始化方法的 ‘二等公民’
只要override init 方法,convenience
的init 方法在子类中可直接使用
But:
- convenience init方法必须调用本类中 的designated初始化方法完成初始化设置。
- convenience的初始化方法不能被子类重写或者是从子类中以super的方式被调用
fatalError
1
2
3
required init(coder: NSCoder) {
fatalError("NSCoding not supported")
}
当子类无需实现,但是又没办法不得不去实现,如上面
如果父类中有个方法无需每个子类都要去实现,但是往往你可能会在子类中用到,这时候你没有注意到,可以通过 fatalError
来强调子类必须实现的方法 , 这样他会在编译的时候打断你。
但是我觉得使用 required
会更好。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MyClass1 {
func methodMustBeImplementedInSubclass() {
fatalError("这个方法必须在子类中被重写")
}
}
class YourClass: MyClass1 {
override func methodMustBeImplementedInSubclass() {
print("YourClass 实现了该方法")
}
}
class TheirClass: MyClass1 {
func someOtherMethod() {
}
}
YourClass().methodMustBeImplementedInSubclass()
TheirClass().methodMustBeImplementedInSubclass()
build failed log
1
2
error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
@discardableResult
忽略返回值,可以不接收
1
2
3
4
5
6
7
@discardableResult func testsss() -> String {
print("test")
// return "suncheng testing"
fatalError("test error")
}
testsss()
通过 fatalError
不再需要指定返回值