标签:
Swift的类型是在C和OC的基础上发展而来的,Int是整型;Double和Float是浮点型;Bool是布尔型;String是字符串。类似OC,Swift也提出了三个集合类型:Array、Set、Dictionary;
除了上述比较熟悉的类型,Swift还增加了OC中没有的类型,比如元组(Tuple);Swift还增加了可选(Optional)类型。
Swift是一个类型安全的语言(甚至以此著称),可选(Optional)就是一个很好的例子。Swift可以让你清除地知道值的类型。如果你的代码期望得到一个String,你却不小心传入一个Int,Swift的类型安全机制会在开发阶段发现这个问题,避免在runtime出错。
在OC以及C中,一个值类型或引用类型数据是常量还是变量由关键字const
决定。在Swift中,在没有const这一说喽。
Swift使用let来声明常量,使用var来声明变量;
Swift在声明一个变量或者常量可以携带类型信息,也可以不携带。
P.S:声明变量/常量时,不指明类型而让Swift编译器隐式处理的这种行为被称为『类型推测』(Type Inference),后文有更详细介绍。
本来常量和变量是编程语言里非常基础的概念,没啥好讲的,但Swift世界里,有些许不同,在赋值过程中,需要注意:
var a: Int
或let b: NSObject
),在其他语言中,系统往往会在这种情况下为它们分配一个默认值,譬如OC会设置默认值0或者nil;但这在Swift的世界里是不可能的,Swift不会为它们设置任何默认值,无论是在什么时候;var a:Int; print("a = \(a)")
是不合法的);第3点意味着:
let aInt: Int = 0; aInt = 5
不合法,常量只能进行一次初始化;var aObject: NSObject; aObject = nil
不合法,右值nil
与NSObject类型不匹配;var aInt: Int; aInt = 0.0
不合法,右值0.0
与Int类型不匹配;说明:
总之,一定要深刻理解到Swift是一门类型安全的语言,《The Swift Programming Language》是这么说的:
Swift is a type safe language. A type safe language encourages you to be clear about the types of values your code can work with. If part of your code expects a
String
, you can not pass it anInt
by mistake.
显然,『类型推测』在处理引用类型时非常便利,这会使得代码更简洁;但是在处理值类型时可能会有些许麻烦,譬如1.0推断为float还收double?在这种记忆力不是特别牢靠(不太确认)的情况下最好还是显式写出变量/常量的类型吧。
「静态局部变量」、「静态全局变量」、「全局变量」这些是C语言里的概念,在Swift似乎不存在。
正如上文所阐述的,Swift是一门『类型安全』的语言,在对对象赋值时,左值类型和右值类型必须匹配,否则无法通过编译;但在OC中,有非常非常多的机会与nil指针打交道,譬如:
Swift的创建是基于Objective-C的,何况还得保证与之兼容,必然考虑到了这个问题,Swift中能够赋值nil的类型叫「可选类型」(optional
)。
C和OC中并没有可选这个概念。在OC的对象世界里,一个指针要么对应这一个对象,要么对应着nil;很多时候我们不知道这个指针到底是空指针,还是有一个有效的对象与之对应,所以我们在OC中经常会写大量大量的if
语句判断某个指针是否为空。而在Swift中,不需要这么麻烦,因为它是一门类型安全的语言,NSObject类型变量在运行时一定有一个NSObject对象与之对应,不可能是nil值。想想这个就激动,想象一下,以前在OC中调用具有返回值的方法时经常需要对返回值进行判断,因为必须要考虑它可能返回nil啊,譬如:
NSMutableArray *aArray = [NSMutableArray array]; NSString *aStr = [self aFuckMethod]; // aFuckMethod的实现代码不可见,不知道一定会返回一个NSString if (aStr) { [aArray addObject:aStr]; }
如果在Swift中,aFuckMethod的
原型为func aFuckMethod() -> String
,则清晰表明了aFuckMethod方法一定会返回一个非String类型对象,那么上面一段代码就可以省掉那个if语句了;对比Swift,确实感觉到了OC是一个门太落后的语言,太罗嗦了!
回过头来阐述Swift的optional
。简而言之:
You use
optionals
in situations where a value may be absent. An optional says:* There is a value, and it equals x
or* There is not value at all
相对于OC,Swift的optionals
对值类型(譬如整型、结构体)和引用类型(类对象)的处理更具一致性
。在OC中,一个方法要不返回一个对象要不返回nil,后者表示『缺乏一个合法的对象』;然而,这只对对象起作用;对于结构体、基本的C类型或者枚举都不起作用,处理这些类型,OC方法一般会返回一个特殊值(譬如NSNotFound)来暗示值缺失,这种方法会假设方法的调用者知道并有意识对特殊值进行判断。然而,Swift的optionals
可以让你暗示任意类型的缺失,并不需要一个特殊值。
P.S:稍微体会一下,就会意识到Swift的optional
高明多了。
Optional类型默认值
在OC中,若声明一个对象(指针)但不赋值,系统会默认将之设置为nil;在Swift中也类似,对于一个optional,若不对其赋值,则默认为nil,这可不是我瞎说,文档有说明:
If you define an optional variable without providing a default value, the variable is automatically set to nil for you.
P.S:似乎这是Swift唯一为变量/常量设置默认值的时机。
简而言之,你可以对一个optional变量赋值nil,也可以赋值相应的对象。
在OC中,我们经常需要对一个类类型指针进行判断,判断它是否为nil;在Swift中使用optional也不省心,也常常需要写if语句判断,只是Swift中提供了更多丰富的处理方式。
强制解析(Foreced Unwrapping)符!
You can use an if
statement to find out whether an optional contains a value by comparing the optional against nil
. You perform this comparison with the ==
or !=
.
当你确定可选包确实含值之后,你可以在可选的名字后面加一个感叹号!
来获取值。这个惊叹号表示『我知道这个可选有值,请使用它』,这被称为可选值的强制解析
(forced unwrapping),如下:
let strNumber = "42" var convertNumber: Int? convertNumber = strNumber.toInt() if convertNumber != nil { println("转换后的结果为:\(convertNumber!)") }
值得注意的是,使用!
来获取一个不存在的可选值会导致runtime error。因此使用!
强制解析前,一定要确定optional
包含一个非nil的值。
总之,一定要记住,惊叹号!
对于optional
而言是『强制解析符』,而不是仅仅是『解析符』,这可不是咬文嚼字,虽然只有两字之差,但意思差远了。
可选绑定(Optional Binding)
使用可选绑定(optional binding)来判断optional
是否包含值,如果包含就把值赋给一个临时常量或者变量。可选绑定可以用在if
和while
语句中来对可选的值进行判断并把值赋给一个常量或者变量,如下:
let strNumber = "42" if let actualNumber = strNumber.toInt() { println("转换后的结果为:\(actualNumber)") }
这段代码可以理解为:
如果strNumber.toInt()
返回的optional
包含一个Int值,则创建一个叫actualNumber的新常量(actualNumber为Int类型)并将可选包含的值赋给它。
这段『可选绑定』的代码显然比前一段『强制解析』的代码要简短一些,可是,我总觉得Swift的这一部分设计不好,晦涩难懂。首先,
下意识里,let actualNumber = strNumber.toInt()
等价两句代码:let temp = strNumber.toInt()
和let actualNumber = temp
,得到的actualNumber应该是一个optional啊,怎么文档给出的解释暗示actualNumber是一个Int类型变量呢?Fuck!
『隐式解析可选』作为右值?
『隐式解析可选』似乎比普通optional更安全,既然这么好,为什么不放弃前面的普通optional呢?似乎是不行的,文档这么说:
Do not use an implicitly unwrapped optional when there is a possibility of a variable becoming
nil
at a later point. Always use a normal optional type if you need to check for anil
value during the lifetime of a variable.
元组(tuples)早已经是很多高级语言(譬如Python)的中重要组成成分了,它用来把多个值组合成一个复合值,而这些值可以是任意类型(无所谓变量还是常量,无所谓值类型还是引用类型,无所谓optional还是non-optional),并不要求是相同类型。
分解元组(Decompose Tuple)
Swift中的元组分解(decompose)和Python中差不多,你可以使用如下语法将一个元组分解成单独的常量和变量:
let http404Error = (404, "Not Found") // http404Error的类型是(Int, String),值是(404, "Not Found") var (status, statusMessage) = http404Error
在decompose时,如果只需要一部分元组信息,使用_
来标记要忽略的部分。
Tuple支持下标操作
可以使用下标访问一个元组中指定的元素,譬如http404Error.0
表示访问上述元组http404Error的第一个元素(值为404的Int型)。
给Tuple元素命名
使用下标访问Tuple元素难免不够完美,毕竟数字太冰冷了;Swift的Tuple还支持给Tuple元素命名,譬如:
let http404Error = (status: 404, message:"Not Found") println("状态码:\(http404Error.status), 信息:\(http404Error.message)")
根据我的理解,Tuple并不算一种类型(事实上Swift中也不存在所谓的Tuple
类型),它更应该看成是Swift所支持的一种语言特性(语法)。Tuple看起来像数组,但显然不同于数组,数组可是一种数据类型,数组包括大量的功能方法,「元组」是不存在所谓的方法的。也正因为如此,元组的使用场景比较单一,一般用来临时组织数据(譬如组织函数/方法的返回值和参数)。
标签:
原文地址:http://www.cnblogs.com/FightingLuoYin/p/4607706.html