假设我有这门课:
class EvenNumber {
var num: Int
var stringValue: String
init?(n: Int) {
guard n % 2 == 0 else { return nil }
self.num = n
}
init?(str: String) {
guard let n = Int(str) else { return nil }
self.init(n: n)
//set stringValue?
}
}
Run Code Online (Sandbox Code Playgroud)
在init需要一个字符串的 中,我将委托回需要一个 的那个Int。我如何知道它是否成功以便我可以继续初始化?这里正确的语法/常见模式是什么?
您不需要检查委托初始化程序是否成功。如果委托初始化程序失败,则整个初始化过程都会失败。
这在这段代码中很明显:
class EvenNumber {
var num: Int
var stringValue: String
init?(n: Int) {
guard n % 2 == 0 else { return nil }
self.num = n
stringValue = "" // you forgot to initialise stringValue in both of your initialisers
}
// you forgot "convenience"
convenience init?(str: String) {
guard let n = Int(str) else { return nil }
self.init(n: n)
print("hello")
stringValue = ""
}
}
EvenNumber(str: "5")
Run Code Online (Sandbox Code Playgroud)
“hello”不会被打印,这意味着如果失败,其余部分init(str:)不会被执行init(n:)。
这是一些支持文档(您需要向下滚动一点,在“初始化失败的传播”下):
在任何一种情况下,如果您委托给另一个导致初始化失败的初始化程序,则整个初始化过程会立即失败,并且不会执行进一步的初始化代码。
(为了完整起见,包含此部分。)
现在您(或将来遇到这个问题的任何人)可能会问,“但是如果委托初始化程序失败,我想做其他事情怎么办?” 在这种情况下,您必须检查导致初始化程序失败的条件:
if n % 2 == 1 {
self.init(n: n)
} else {
// do something else
}
Run Code Online (Sandbox Code Playgroud)
为什么这么“笨拙”?好吧,假设你可以这样做(警告:虚构的语法):
if self.init(n: n) {
// success!
} else {
// fail
}
Run Code Online (Sandbox Code Playgroud)
要到达“失败”分支,我们必须已经运行了self.init(n:)。self.init(n:)在失败之前,可能已经初始化了一些let属性。回想一下,let属性只能初始化一次。所以现在self.init(n: n)已经执行了,但是编译器不知道哪些let属性已经被初始化了。看到问题了吗?编译器如何验证您是否已在“失败”分支中将每个属性初始化一次?
| 归档时间: |
|
| 查看次数: |
136 次 |
| 最近记录: |