运算符是用来检查,改变,或者合并值的特殊的符号或者短语.例如加号(+)将两个数字相加,像let i= i+2,逻辑和运算符结合两个布尔值,像if enteredDoorCode && passedRetinaScan。
swift支持大多数标准C运算符并且提升了多个排除普通编码错误的功能。分配符(=)不返回值,避免在享用相等于(==)时而错误的使用了它。算术运算符(+,-,*,/等等)检查并且不允许值溢出,为了避免当使用数字时储存的数字比他们的类型所允许的范围更大或者更小,像Overflow Operators中描述的。
swift同事提供了C中没有的范围运算符,例如a..<b跟a...b,是表示值范围的简写。
这个章节描述了swift找那个普通的运算符。Advanced Operators介绍了swift的advanced运算符,并介绍了如何定义自定义的运算符并未自己的自定义类型
术语(Terminology)
运算符有一元的,二元的,或者三元的。
- 一元操作符在一个单一目标上操作。一元前置操作符在他们的目标之前立即出现(例如 !b),一元后置操作符在他们的目标之后立即出现(例如c!)。
 - 二元操作符在两个目标上操作,并且是在中间,因为他们出现在另个目标之间。
 - 三元操作符在三个目标上进行操作。像C一样,swift只有一个三元操作符,三项运算符(a?b:c)。
 
操作符影响的值使操作数。表达式1+2中,+符号是一个二元操作符,并且它的操作数是值1和2.
分配操作符(Assignment Operator)
分配符(a=b)用b的值初始化或者更新a的值:
let b = 10
var a = 5
a = b
// a is now equal to 10分配符的右侧是一个有多个值的元祖,它的元素可以一次分解成多个常量或者变量:
let (x, y) = (1, 2)
// x is equal to 1, and y is equal to 2不像C或者Objective-C中的分配符,swif中的分配符本身不返回值。下面的语句是不合法的:
if x = y {
    // This is not valid, because x = y does not return a value.
}这个特性防止想用等于符(==)却意外使用分配符。通过让if x=
y不合法,swift帮你在你的代码中避免这一类的错误。
算术运算符(Arithmetic Operators)
swift使支持所有数字类型支持四个标准算术运算符:
- 加号(+)
 - 减号(-)
 - 乘号(*)
 - 除号(/)
 
1 + 2       // equals 3
5 - 3       // equals 2
2 * 3       // equals 6
10.0 / 2.5  // equals 4.0不像C和Objective-C中的算术运算符,swift算术运算符默认不允许值溢出。你可以通过选择swift的溢出操作符(例如a&+b)来选择溢出表现的值。
加号支持String类型的值:
"hello, " + "world"  // equals "hello, world"取余符号(Remainder Operator)
取余操作符(a%b)计算a中是b的多少倍,返回余下的值(就是余数).
取余操作符也是其他语言中的模运算符。不过,swift中负数的表现意思是取余而不是模运算。
这里是取余运算如何进行。计算9%4,先计算出9中有几个4:
9中有两个4,余数是1.
swift中,按下面这样写:
9 % 4    // equals 1决定a%b的大难,取余运算符计算下面的方程并把余数作为输出返回:
a = (b x some multiplier) + remainder
some multiplier是a中b最大的倍数。
将9和4写入这个方程式:
9 = (4 x 2) + 1
计算负数a的余数时一样的方法:
-9 % 4   // equals -1将-9和4写入方程式中:
-9 = (4 x -2) + -1
返回的余数是-1.
负数b的符号省略。这意味着a%b和a%-b的结果是一样的
一元减号操作符(Unary Minus Operator)
几何值得符号可以使用前置-来切换,叫做一元减号操作符:
let three = 3
let minusThree = -three       // minusThree equals -3
let plusThree = -minusThree   // plusThree equals 3, or "minus minus three"一元减号运算符直接在值出现地方的前面,没有空格。
一元加操作符(Unary Plus Operator)
加号操作符值时返回它操作的值,没有改变:
let three = 3
let minusThree = -three       // minusThree equals -3
let plusThree = -minusThree   // plusThree equals 3, or "minus minus three"即使加号没有做任何操作,可以在负数使用负号的时候用它为正数提供对称性。
组合分配操作符(Compound Assignment Operators)
和C一样,swift提供了分配符与其他操作符结合的组合分配符。加号分配操作符(+=)是一个例子:
var a = 1
a += 2
// a is now equal to 3a+=2是a= a+2的简写。实际上,加号跟分配符结合成一个操作符,它们的任务同时进行。
分配操作符的组合没有返回值。不能写成:let b = a += 2
查看更多操作符的信息前往swift标准库Operator Declarations。
比较操作符(Comparison Operators)
swift听过了所有C的比较符:
- 等于(a==b)
 - 不等于(a!=b)
 - 大于(a > b)
 - 小于(a<b)
 - 大于等于(a>=b)
 - 小于等于(a<=b)
 
swift 也提供了两个恒等操作符(===跟!===),用来测试两个对象的引用是否指向相同的对象实例。更多信息查看Identity Operators。
每一个比较符返回bool值指明语句是否正确:
1 == 1   // true because 1 is equal to 1
2 != 1   // true because 2 is not equal to 1
2 > 1    // true because 2 is greater than 1
1 < 2    // true because 1 is less than 2
1 >= 1   // true because 1 is greater than or equal to 1
2 <= 1   // false because 2 is not less than or equal to 1比较符经常在条件语句中使用,例如if语句:
let name = "world"
if name == "world" {
    print("hello, world")
} else {
    print("I'm sorry \(name), but I don't recognize you")
}
// Prints "hello, world", because name is indeed equal to "world".更多if语句信息,查看Control Flow.
如果两个原有有相同的类型和相同数量的值,可以比较两个元祖。元祖从左到右进行比较,一次一个值,直到比较发现两个值不相等。比较的两个值,比较的结果决定整个元祖比较的结果。若果全部元素相等,那么元祖相等。例如:
(1, "zebra") < (2, "apple")   // true because 1 is less than 2; "zebra" and "apple" are not compared
(3, "apple") < (3, "bird")    // true because 3 is equal to 3, and "apple" is less than "bird"
(4, "dog") == (4, "dog")      // true because 4 is equal to 4, and "dog" is equal to "dog"上面的例子中,可以看到在第一行从左到右的比较。因为1比2小,(1,“zebra”)比(2,“apple”)小,元祖中的其他值都忽略。“zebra“没有比”apple“小没有事,因为比较已经有第一个元素决定出来了。不过,如果第一个元素是相等的,他们第二个元素再比较--这是在第二行跟第三行发生的事情。
只有当一个操作符可以分别应用到元祖的值,那么元祖可以使用这个操作符来进行比较。例如,下面代码中展示的,因为两个String和Int值可以使用<操作符进行比较,所以两个(String,Int)类型的元祖可以进行比较。相反的,两个(String,Bool)类型的元祖不能使用<操作符进行比较,因为<操作符不能用在Bool类型的值上。
("blue", -1) < ("purple", 1)        // OK, evaluates to true
("blue", false) < ("purple", true)  // Error because < can't compare Boolean valuesswift标准库中有对少于7个元素的元祖进行比较的操作符。如果要比较有7个或更多元素的元祖,你要自己实现比较操作符。
三相运算符(Ternary Conditional Operator)
三相运算符是有三个部分的特殊费操作符,形式是question ? answer1 : answer2。是在question是true或者false的基础上计算两个表达式中的一个的简写。如果question是true,计算answer1并且返回它的值;不然,计算answer2并返回它的值。
三相运算符是下面代码的简写:
if question {
    answer1
} else {
    answer2
}下面的例子,计算列表行高。如果行有头部,行高应该比内容高度多出50点,如果没有头则多出20点:
let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50 : 20)
// rowHeight is equal to 90上面例子是下面代码的简写:
let contentHeight = 40
let hasHeader = true
let rowHeight: Int
if hasHeader {
    rowHeight = contentHeight + 50
} else {
    rowHeight = contentHeight + 20
}
// rowHeight is equal to 90第一个例子中使用三项运算符意味着可以在一行代码中设置正确的值,比第二个例子中的代码简洁多了。
三项运算符为决定两个表达式用哪一个提供了高效的简便形式。不过使用三项运算符要当心。如果过度使用,它的概念会导致代码阅读性差。避免把多个三相运算符的实例结合到一个组合语句中。
Nil-合并 操作符(Nil-Coalescing Operator)
如果a有值nil-coalescing运算符(a??b)将可选类型a解包,或者如果a是nil返回默认值b。表达式a通常是一个可选类型。表达式b的类型一定与a的匹配。
nil-coalescing操作符是如下代码的简写:
a != nil ? a! : b上面代码当a不是nil时使用三项运算符并且强解包(a!)来操作a中的值,否则返回b。nil-coalescing操作符提供了一个更优雅的形式来把条件检查和解包封装到简洁和阅读性更强的形式中。
如果值时非nil的,b的值不会计算。这就是短路计算。
下面的例子使用了nil-coalescing操作符来在默认颜色名称和可选的用户默认颜色名称之间做选择:
let defaultColorName = "red"
var userDefinedColorName: String?   // defaults to nil
var colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName is nil, so colorNameToUse is set to the default of "red"userDefinedColorName变量定义的是一个可选String类型,有一个nil默认值。因为userDefinedColorName是可选类型,你可以使用NIl-coalescing操作符来计算它的值。在上面的例子中,操作符用来决定名为colorNameToUse的变量的初始化值。因为userDefinedColorName是nil,表达式userDefinedColorName ?? defaultColorName返回defaultColorNmae或者”red“。
如果给userDefinedColorName分配了一个值并且使用nil-coalescing操作符再检查一遍,userDefinedColorName内部解包出来的值用来替代默认值:
userDefinedColorName = "green"
colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName is not nil, so colorNameToUse is set to "green"范围操作符(Range Operators)
swift包括多个范围操作符,表达一个范围值的简写.
闭合范围操作符(Closed Range Operator)
闭合范围操作符(a...b)定义了从a到b的范围,并且包括值a和b。a的值必需大于b。
闭合区间操作符当要全部遍历区间时是有用的,期盼区间的全部的值都要用,像for-
in循环:
for index in 1...5 {
    print("\(index) times 5 is \(index * 5)")
}
// 1 times 5 is 5
// 2 times 5 is 10
// 3 times 5 is 15
// 4 times 5 is 20
// 5 times 5 is 25更多for-in循环的信息,查看Control Flow.
半开区间操作符(Half-Open Range Operator)
半开区间操作符(a..<b)定义了一个从a到b的区间,但是不包括b。成为半开区间是因为它包含它的第一个值,但不包括最后一个值。和闭合区间操作符一样,a的值不能大于b的值。如果a的值等于b的值,区间的结果就是空的。
半开区间在遍历从零开始的列表例如数组时特别有用,计数到但不包括列表的长度:
let names = ["Anna", "Alex", "Brian", "Jack"]
let count = names.count
for i in 0..<count {
    print("Person \(i + 1) is called \(names[i])")
}
// Person 1 is called Anna
// Person 2 is called Alex
// Person 3 is called Brian
// Person 4 is called Jack注意数组包含四个项目,但是0..<count只算到3(数组中最后一个项目的索引),因为它是半开区间。更多关于array的信息,查看Arrays.
单侧区间(One-Sided Ranged)
闭合区间操作符有从在一个方向尽可能的继续的区间的选择形式--例如,一个区间包括数组的索引2一直到最后的全部的元素。那些情况下,你可以忽略区间操作符一侧的值。这种区间乘坐单侧区间因为操作符只有一侧的值。例如:
for name in names[2...] {
    print(name)
}
// Brian
// Jack
for name in names[...2] {
    print(name)
}
// Anna
// Alex
// Brian半开区间也有只有最后的值的单侧形式。就像两侧都有值,最后的值不是区间的一部分。例如:
for name in names[..<2] {
    print(name)
}
// Anna
// Alex单侧区间可以在另外的上下文中使用,不只是用于下标。不能遍历忽略了第一个值的单侧区间,因为不清楚遍历从哪里开始。可以遍历忽略了最后值的区间;不过,因为区间会无限继续,确定你给循环添加了明确的结束条件。也可以检测单边区间是否包含指定的值,和下边代码显示的一样。
let range = ...5
range.contains(7)   // false
range.contains(4)   // true
range.contains(-1)  // true逻辑操作符(Logical Operators)
逻辑操作符修改或者合并布尔逻辑值true和false。swift支持三种C语言基础的标准逻辑操作符:
Logical NOT (!a)Logical AND (a && b)Logical OR (a || b)逻辑否操作符(Logical NOT Operator)
逻辑否(!a)转变布尔值,所以true变为false,false变为true。
逻辑否是一个前置操作符,立即出现在他操作的值的前面,不需要空格。可以读作”not a“,像下面例子展示:
let allowedEntry = false
if !allowedEntry {
    print("ACCESS DENIED")
}
// Prints "ACCESS DENIED"语句if !allowedEntry可以读作”if not allowed entry“。后面一行只有”not allowed entry“是true的时候才执行,allowedEntry是false。
像例子中,仔细选择布尔值常量跟变量的名字有助于保持代码的可读性和简洁,避免双否定或者迷惑的逻辑语句。
逻辑和操作符(Logical AND Operator)
逻辑和操作符(a&&b)创建两个值都是true表达式也为true的逻辑表达式。
如果任何一个值时false,整个表达式都是false。实际上,第一个值是false,第二个值不会计算执行,因为他不可能使整个表达式等于true。这就是short-circuit算法。
这个例子计算两个布尔值并且只有两个值是true时才允许执行:
let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// Prints "ACCESS DENIED"逻辑或操作符(Logical OR Operator)
逻辑或操作符(a||b)是一个由两个相邻的竖线字符组成的中间操作符。可以用它来创建逻辑表达式,两个值只有一个是true整个表达式也是true。
像上面的逻辑和操作符,逻辑或操作符使用short-circuit算法来计算表达式。若果逻辑或表达式左边是true,右侧不执行,因为它不会改变整个表达式的输出。
下面的例子中,第一个布尔值(hasDoorKey)是false,但是第二个(knowsOverridePassword)是true。因为有一个值是true,整个表达式也是true,操作也是允许的:
let hasDoorKey = false
let knowsOverridePassword = true
if hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// Prints "Welcome!"结合逻辑操作符(Combining Logical Operators)
可以结合多个逻辑操作符来创建一个长的符合的表达式:
if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// Prints "Welcome!"这个例子使用了多个&&和||边大师来创建一个长的表达式,不过,&&和||操作符仍然值操作两个值,所以这是三个链在一起的小的的表达式。这个表达式可以解读为:
如果我们输入了正确的门密码并且通过了retina扫描,或者如果我们有一把正确的门钥匙,或者如果我们知道紧急通过密码,那么允许操作。
在enteredDoorCode,passedRetinaScan,和hasDoorKey三个值的基础上,第一个两个子表达式是false。不过,紧急通过密码是知道的,所以整个组合表达式计算仍是true。
swift逻辑表达式&&和||从左结合的,意味着多个逻辑操作符的组合表达式先计算最左侧的子表达式。
明确的括号(Explicit Parentheses)
有的时候当不是很有必要的时候使用括号很有用,使复杂表达式的目的变得更清晰。在上面操作门的例子中,在第一个组合表达式的部分增加括号可以使它的目的更明确:
if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// Prints "Welcome!"括号使在整个逻辑中前两个值清晰地作为一个独立的情况的一部分。组合表达式的输出没有变化,但是整个目的变得清晰了。可读性通常比简洁更重要;当括号可以帮助你是目的更明确时,多使用它。