可选类型与构造函数
导语
在swift快速入门时,发现自己很难理解可选类型
所以本文通过一些类的互相调用来加强对可选类型的理解
本文涉及的内容有 类,构造函数,可选类型的定义和使用
基本知识
1. 定义及初始化
可选类型是swift中特有的,c和objective-c中都没有这个概念。
当你定义一个类型为可选类型时,它可以为nil,或者可以一个值
//申明一个可选型字符串,未初始化默认为nil
var optionStr: String?
//申明一个可选性Int常量,无初始化
let num: Int?
我们做个实验,令num = 1,再num = 2,结果如下图。
我们可以看到,在第一次 num = 1,其实是对num进行初始化,所以并不会报错。
而当第二次赋值时,则系统提示错误,说常量num只能初始化一次。
总结
如果申明的是var 可选型变量,则初始化的值为nil
如果申明的是let 可选型常量,则第一次赋值操作为初始化,并不会自动初始化为nil
2. 强制类型转换时的option
强制类型转换时,如Int()操作,不是所有的String都可以转换为Int,所以在这时候就体现的可选型的作用,要么返回Int,要么返回nil
//converedNumber和converedNum被推测为类型"Int?"
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
let possibleNum = "hello"
let convertedNum = Int(possibleNum)
深入探讨
1.初始化和可选型的关系
先定义一个Room类
class Room {
let name: String
//init中可以初始化name的值
init(name: String) {self.name = name}
}
我们尝试一下一些错误的定义:
1. 如果在类中申明实例变量,则必须有构造函数或者在申明变量时对其进行初始化,而可选型的变量是可以不初始化的,因为系统会将其初始化为nil
2. 如果在类中申明常量,则不管是否是可选型,都必须初始化,因为常量是没有办法修改其值的,所以必须初始化
2.type! 和type? 的区别
再定义一个Residence类,Person类
class Person {
//此处residence为可选型,初始值为nil
var residence: Residence?
}
class Residence {
var rooms = [Room]()
var numberOfRooms: Int {
return rooms.count
}
subscript(i: Int) -> Room {
get {
return rooms[i]
}
set(newValue) {
rooms[i] = newValue
}
}
func printNumberOfRooms() {
print("The number of rooms is \(numberOfRooms)")
}
}
然后申请一个Person实例john, 当调用实例方法时出错
原因在于,我们在Person中申明的是Residence?类,此处调用时
//要么使用
let roomCount = john.residence?.numberOfRooms
//要么使用
let roomCount = john.residence!.numberOfRooms
类型type?和类型type!中符号的意思
?: 告诉编译器我不确定这个变量是否有值,有值就继续调用,否则返回nil
!: 告诉编译器这个变量是肯定有值的,否则报错
我们再尝试一下别的错误
这里的原因是我们Person类中申明Residence?时没有初始化,所以默认初始化为nil,而此处用!来解析绑定,就会导致错误
我们可以在Person类中对residence进行初始化
class Person {
//有两种初始方式,我推荐用构造器初始化
var residence: Residence? = Residence()
// init() {
// residence = Residence()
// }
}
由于初始化后,residence的值不再为空,则调用john.residence!就不会出错
举例说明(iOS)
此问题来自swift里!号的意义
楼主的的问题是不明白为什么有时候用!,有时候用?
var amiteLbl: UILabel?
self.amiteLbl = UILable(frame:CGRectMake(50, 100, 200, 40))
self.amiteLbl!.text = "I love mixbox"
self.view?.addSubview(self.amiteLbl)
我们分析一下
1.首先我们定义一个UILable?,然后对其进行初始化
2.此时self.amiteLbl!.text的原因是我们对amiteLbl进行了初始化,我们确定其值不为空,所以使用了!
3.而self.view?为什么用的是?呢,因为我们不确定view是否为空,如果此时贸然使用!,当view为nil时,程序就会崩溃。
4.我们也可以翻译一下self.view?.addSubview(self.amiteLbl)
if let theView = self.view {
theView.addSubview(self.amiteLbl)
} else {
return nil
}
参考:
苹果官方文档