Swift语言学习(三)

原文链接:http://www.ioswift.org/

6.基本操作

运算符是一种用来检查,改变,或组合值的特殊的符号或短语。例如,+ 将两个数相加(let i = 1 + 2)。更复杂的运行算,如逻辑与运算符 &&(如 if enteredDoorCode && passedRetinaScan),或者 让 i 便捷加 1 的运算符自增运算符 ++i 等。


Swift 支持大多数 C 语言的运算,并改进了一些特性来消除常见的编码错误。赋值运算符( = )没有返回值,以防止它被误用为等于运算符( = = )。算术运算符(+-*/%等等)会自动检测以防止溢出,避免由于变量大于或小于其类型所能承载的范围时导致的异常结果。当然你可以使用 Swift 的溢出运算符来实现溢出。

与 C 语言不同的是,Swift 可以对浮点数进行取余运算(%),Swift 还提供了表达两数之间的值的区间运算符:a..ba...b ,方便表达一个区间内的数值。

本章节只描述了 Swift 的基本运算符,高级运算符包含了高级运算符,以及如何自定义运算符和运算符重载。

6.1.术语

运算符有一元,二元和三元运算符。


 一元运算符只操作一个对象(如-a)。一元运算符分前置和后置,前置运算符排在操作对象之前(如!b),后置运算符需排在操作对象之后(如i++)。


 二元运算符操作两个对象(如2 + 3),二元运算符都是中置的,因为它出现在两个操作对象之间。


 三元运算符操作三个对象,和 C 语言一样,Swift 只有一个三元运算符,就是三元条件运算符(a ? b : c)。
 
运算符操作的对象叫操作数,在表达式 1 + 2 中,加号 + 是二元运算符,它的两个操作数是 1 和 2。

6.2.赋值运算符

赋值运算 = 。比如: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 的赋值运算符不同,Swift 的赋值运算符没有返回值。所以下面的代码是错误的:

if x = y {
    // this is not valid, because x = y does not return a value
}

这个功能可以防止赋值运算符 (=) 被用作逻辑相等运算符 (= =)。if x = y 是无效的,Swift 从底层帮你避免了这些代码错误。

6.3.算数运算符

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"

两个 Character 值或一个 String 和一个 Character 值相加会生成一个新的 String 值:

let dog: Character = "d"
let cow: Character = "c"
let dogCow = dog + cow
// dogCow is equal to "dc"

6.4.取余运算符

取余运算(a % b)就是我们数学中的求余数运算。
注意:取余运算(%)在其他语言中也叫取模运算。然而严格说来,我们看该运算符对负数的操作结果,"取余"比"取模"更合适些。

来看一个取余的例子,计算9 % 4:

9是4的2倍,余数是1(用橙色标出)。


在 Swift 中这么写:

9 % 4    // equals 1

为了得到a % b的结果,% 计算了以下等式,并输出余数作为结果:

a = (b × 倍数) + 余数
 
当倍数取最大值的时候,适合在a中。把9和4代入等式中,我们得 1:
9 = (4 × 2) + 1


同样的方法,我来们计算 -9 % 4:

-9 % 4   // equals -1

在对负数 b 求余时,b 的符号会被忽略。所以 a % b 和 a % -b的结果是相同的。

6.5.浮点数取余计算

不同于 C 和 Objective-C,Swift 中是可以对浮点数进行取余。

8 % 2.5   // equals 0.5

这个例子中,8 除以 2.5 等于 3 余 0.5,所以结果是 Double 类型的值 0.5 。

6.6.自增和自减运算符

和 C 一样,Swift 提供了对变量本身加1或减1的自增(++)和自减(--)的运算符。其操作对象可以是整型和浮点型。

var i = 0
++i      // i now equals 1

每调用一次 ++i ,i 的值就会加 1 。实际上,++i 是 i = i + 1 的简写,而 --i 是 i = i - 1 的简写。
 
++ 和 -- 既是前置又是后置运算。++i ,i ++,--i 和 i-- 都是有效的写法。
需要注意的是这些运算符修改了 i 后有一个返回值。如果只想修改 i 的值,可以忽略返回值。如果想使用返回值,你就需要注意前置和后置操作对应的返回值是不同的。

     当 ++ 前置的时候,先自増再返回。
     当 ++ 后置的时候,先返回再自增。


如:

var a = 0
let b = ++a
// a and b are now both equal to 1
let c = a++
// a is now equal to 2, but c has been set to the pre-increment value of 1

上述例子中,let b = ++a 先把 a 加 1 了再返回 a 的值。所以 a 和 b 都是新值 1。
而 let c = a++,是先返回了 a 的值,然后 a 才加 1。所以 c 得到了 a 的旧值 1 ,而 a 加 1 后变成 2 。


除非你需要使用 i++ 的特性,不然推荐你使用 ++i 和 --i ,因为先修改后返回这样的行为更符合我们的逻辑。

6.7.一元负号算符

数值的正负可以使用前缀(-)(即一元负号)来切换:

let three = 3
let minusThree = -three       // minusThree equals -3
let plusThree = -minusThree   // plusThree equals 3, or "minus minus three"

一元负号(-)写在操作数之前,中间没有空格。

6.8.一元正号算符

一元正号(+)返回不做任何改变的操作数的值。

let minusSix = -6
let alsoMinusSix = +minusSix  // alsoMinusSix equals -6

虽然一元 + 做无用功,但当使用一元负号来表达负数时,同样使用一元正号来表达正数,这样你的代码会具有对称美。

6.9.复合赋值操作符

和 C 语言一样,Swift 也可以把其他运算符和赋值运算(=)一起组合使用,即是:复合赋值运算符。加赋运算符(+=)就是其中一个例子

var a = 1
a += 2
// a is now equal to 3

表达式 a += 2 是 a = a + 2 的简写,一个加赋运算同时把加法和赋值两件事完成了。

注意:复合赋值运算没有返回值,let b = a += 2 代码是错误。这不同于上面提到的自增和自减运算符。

6.10.比较运算符

Swift 支持所有标准 C 语言中的比较运算符

     等于(a == b)
     不等于(a != b)
     大于(a > b)
     小于(a < b)
     大于等于(a >= b)
     小于等于(a <= b)

注意:Swift 也提供恒等 === 和不恒等 !== 这两个比较符来判断两个对象是否引用同一个对象实例。

每个比较运算都返回了一个布尔值:

 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" {
    println("hello, world")
} else {
    println("I'm sorry \(name), but I don't recognize you")
}
// prints "hello, world", because name is indeed equal to "world"

6.11.三元条件运算符

三元条件运算符比较特殊,它有三个操作数,它的格式是 question ? answer1 : answer2 。简洁的表达出 question 是否成立( true )。如果 question 成立,返回 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
var rowHeight = contentHeight
if hasHeader {
    rowHeight = rowHeight + 50
} else {
    rowHeight = rowHeight + 20
}
// rowHeight is equal to 90

第一段代码使用了三元条件运算符,只要一行代码就可以得到答案,比第二段代码简洁很多。无需 rowHeight 变量,因为在if语句中它的值不需要改变。
三元条件运算符更有效率、更便捷地表达了二选一的选择。注意,过度使用三元条件运算会使代码比较难懂,应避免在一条语句使用多个三元条件运算符。

6.12.区间运算符

Swift 有两个区间运算符:闭区间运算符( a...b )和半闭区间 ( a..b ) 运算符。下面我们来详细介绍

6.13.闭区间运算符

闭区间运算符(a...b):包含从 a 到 b (包括 a 和 b )之间的所有的值。

闭区间运算符在迭代所有值的时候非常有用,比如在 for-in 循环中:

for index in 1...5 {
    println("\(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

6.14.半闭区间运算符

半闭区间运算符(a..b):定包含从 a 到 b 但不包括 b 的区间内的所有的值。

被称为半闭区间,是因为该区间包含第一个值,不包括最后一个值。
 
半闭区间主要用于从 0 开始的列表(如数组),可以方便地取值从 0 到列表的长度(但不包括)。

6.15.逻辑运算符

逻辑运算符主要操作返回 Bool 类型的表达式。Swift 支持 C 语言的三个标准逻辑运算符 :
     逻辑非( !a
     逻辑与( a && b
     逻辑或( a || b

6.16.逻辑非运算符

逻辑非运算符( !a ):对一个布尔值取反,也就是 true 变成 false ,false 变成 true。
它是一个前置运算符,必须在操作数之前,且中间不能有空格。读作 非a ,看下面的例子:

let allowedEntry = false
if !allowedEntry {
    println("ACCESS DENIED")
}
// prints "ACCESS DENIED"


if !allowedEntry 语句可以读作 “ 如果 非allowedEntry ”。

如果“ 非allowedEntry ”为true,即 allowEntry 为 false 时,执行中括号中代码。

小心地使用布尔常量或变量有助于代码的可读性,尽量避免使用双重或混乱的逻辑非运算语句。

6.17.逻辑与运算符

逻辑与运算符(a && b):当 a 和 b 的值都为 true 时,整个表达式的值为 true。
只要任意一个值为 false ,整个表达式的值就为 false。事实上,如果第一个值为 false,那么是不去计算第二个值的,因为它已经不可能影响整个表达式的结果了。这被称做 "短路计算(short-circuit evaluation)"。


下面的例子,只有两个 Bool 值都为 true 值的时候才允许访问:

let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
    println("Welcome! ")
} else {
    println("ACCESS DENIED")
}
// prints "ACCESS DENIED"

6.18.逻辑或运算符

逻辑或运算符(a || b):当 a 和 b 中其中一个为 true 时,整个表达式就为true。
同逻辑与一样,逻辑或也是“短路计算”,当左侧的表达式为 true 时,将不再计算右侧的表达式,因为它不可能改变整个表达式的值。


下面例子中,第一个布尔值 hasDoorKey 为false,但第二个值 knowsOverridePassword 为true,所以整个表达是true,于是允许访问:

let hasDoorKey = false
let knowsOverridePassword = true
if hasDoorKey || knowsOverridePassword {
    println("Welcome! ")
} else {
    println("ACCESS DENIED")
}
// prints "Welcome! "

6.19.组合逻辑运算符

我们可以组合多个逻辑运算来创建一个更长的复合逻辑运算:

if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
    println("Welcome! ")
} else {
    println("ACCESS DENIED")
}
// prints "Welcome! "

这个例子使用了多个 && 和 || 创建了一个复合逻辑。但无论怎样,&& 和 || 始终只能操作两个值。所以这实际是三个简单的简单逻辑组成的操作。


它可以被理解为:如果有正确的进入门的代码并通过了视网膜扫描;或者有一把有效的钥匙;或者有紧急覆盖密码,那么就可以访问。
前两种情况都不满足,所以结果是 false,但是有紧急覆盖密码,所以整个复杂表达式的值还是 true。

6.20.使用括号明确优先级

为了使复杂表达式更容易读懂,可以在合适的地方使用括号(并非必要的)明确优先级。在上面的例子中,给第一个部分加个括号会使它看起来逻辑更清晰:

if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword {
    println("Welcome! ")
} else {
    println("ACCESS DENIED")
}
// prints "Welcome! "

括号使得前两个值成为独立的一部分。虽然有无括号的结果是一样的,但有括号使代码更清晰。代码的可读性比简洁性更重要,所以括号有时候是必要的!

猜你喜欢

转载自usench.iteye.com/blog/2272270