这是我参与更文挑战的第17天,活动详情查看: 更文挑战
可失败的初始化方法
- 可失败的初始化方法:当初始化方法传入无效的参数值,或缺少某种所需的外部资源、或不满足某种必要的条件
- 类、结构体和枚举使用关键字
init?
定义可失败的初始化方法
class Student {
var name: String
init? (name: String) {
if name.isEmpty {
return nil
}
self.name = name
}
}
复制代码
-
可以用
init!
定义隐式解包的可失败初始化方法 -
不允许同时定义参数标签、参数个数、参数类型相同的可失败初始化和非可失败初始化方法
-
可失败初始化方法可以调用非可失败初始化方法,非可失败初始化方法调用可失败初始化方法需要进行解包
-
如果初始化调用一个可失败初始化方法导致初始化失败,那么整个初始化过程都是失败的,并且之后的代码都停止执行
class ClassA{
let str:String!
init?(str:String) {
if str.isEmpty{
return nil
}
self.str = str
}
}
class ClassB:ClassA{
let b:Float
init?(a:String,b:Float) {
if b<1 {
return nil
}
self.b = b
super.init(str: a)
}
}
let c = ClassB.init(a: "1", b: 0) //nil
let d = ClassB.init(a: "", b: 1) //nil
let e = ClassB.init(a: "1", b: 1) //ClassB
复制代码
- 可以用非可失败初始化方法重写一个可失败初始化方法,但是反过来不行
重写可失败初始化
可以用一个不可失败的初始化重新父类可失败初始化,但是不能反过来,重写父类初始化时,返回值要强制解包
class ClassA{
var str:String
init?(str:String) {
self.str = str
if str.isEmpty{
return nil
}
}
}
class classC:ClassA{
var c:String
override init(str: String) {
c = str
super.init(str: str)!
}
}
let cc = classC.init(str:"d") //classC
复制代码
init!可失败初始化
init?
需要解包,init!
直接使用
不管使用哪种形式,都需要判空
必要初始化
如果初始化用required
来修饰,那么意味着子类必须重写该父类的构造器
class ClassA{
var str:String
required init(str:String){
self.str = str
}
}
class classC:ClassA{
var c:String
required init(str: String) {
c = str
super.init(str: c)
}
}
let cc = classC.init(str: "c") //classC
复制代码
如果子类继承的构造器能满足必要初始化的要求,则无须在子类中显式提供必要构造器的实现
class ClassA{
var str:String
required init(){
str = "0"
}
}
class classC:ClassA{
var c = "1"
}
let cc = classC.init() //classC
复制代码
通过闭包或函数设置属性的默认值
在设置存储属性默认值时,可以用函数或者闭包来实现
class SomeClass {
let someProperty: SomeType = {
// 注意: 在这里不能用self, 更不能用其它的属性(即使它有默认值, 因为self还没准备好)或者该类的实例方法,执行这段代码时, 初始化都还没有进行
// 在这个闭包中给 someProperty 创建一个默认值
// someValue 必须和 SomeType 类型相同
return someValue
}()// 最后要加上(), 不然就被当做是个闭包, 而不是这个闭包的结果了
}
复制代码
struct Checkerboard {
let boardColors: [Bool] = {
var temporaryBoard = [Bool]()
var isBlack = false
for i in 1...8 {
for j in 1...8 {
temporaryBoard.append(isBlack)
isBlack = !isBlack
}
isBlack = !isBlack
}
return temporaryBoard
}()
func squareIsBlackAtRow(row: Int, column: Int) -> Bool {
return boardColors[(row * 8) + column]
}
}
复制代码
每当一个新的Checkerboard实例被创建时,赋值闭包会被执行,boardColors的默认值会被计算出来并返回。上面例子中描述的闭包将计算出棋盘中每个格子对应的颜色,并将这些值保存到一个临时数组temporaryBoard中,最后在构建完成时将此数组作为闭包返回值返回。这个返回的数组会保存到boardColors中,并可以通过工具函数squareIsBlackAtRow来查询:
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END