Swift4.1 第二章 Basic Operators

基本运算符

一个运算符是一个特殊的字符或短语,你能够用它来检查,改变,合并值。例如:加号(+)表示两个数相加,例如let i = 1 + 2。还有逻辑运算符 AND (&&)用来关联两个布尔值,例如:if enteredDoorCode && passedRetinaScanhtml

Swift支持大多数标准的C语言的操做符,而且改进了许多特性用来减小常规的编译错误。操做符=不意味着返回一个值,这是为了和赋值运算符==进行区分,避免由于错写为=出现错误。算数运算符(+,-,*,/ 等)会检测并不容许值的溢出,这主要是用来避免由于值过大或者太小而超出它的类型所承载的范围致使异常的结果。你可使用swift溢出的运算符来实现溢出,具体请参照溢出运算符git

Swiftc语言不一样的是,swift提供了区间运算符。例如:a..<ba...b,这方便咱们表达一个区间内的数值。github

这个小节描述了Swift中的基本操做符,高级运算符会包含Swift中的高级运算符,以及如何进行自定义运算符和如何用你本身的方式来实现标准的操做符。swift

术语

运算符分为一元,二元和三元运算符。数组

  • 一元运算符是对单一目标进行操做的(例如-a)。一元运算符有前缀和或追之分,前缀运算符每每出如今操做对象的前面(例如!b),后缀运算符每每出如今操做对象的后面 (例如:c!)
  • 二元运算符是操做对象是两个目标,运算符的位置在操做对象的中间(例如:a+b)。
  • 三元运算符的操做对象是三个目标,和c语言同样,swift只有一个三元运算符,就是三目运算符(a?b:c)。

    受操做符影响的值叫操做者。在表达式1+2中,操做符+是一个二元运算符,它的两个操做者的值是12app

赋值运算符

赋值运算符用于初始化和更新ab的值(例:a=b)。ide

let b = 10
var a = 5
a = b
// 如今a的值为10

若是赋值运算符的右边是一个具备多值的元组,那么它的成员能够被当即分解成多个常量和变量。ui

let (x, y) = (1,2)
//  x的值为1  y的值为2

赋值运算符在swift中和在Objective-C以及C语言中是不一样的,赋值运算符在swift中不会返回一个值。下面的语句是不合法的:spa

if x = y {
    // 这是不合法的,由于等式 x = y没有返回值。
}

Swift中的这个特性避免了在使用等式运算符(==)中由于误用赋值运算符(=)而致使的错误。当语句if x = y 不合法的时候,swift会在你的代码中提示你避免出现这样的错误。翻译

算术运算符

swift为全部的数字类型提供了四种标准的算术运算符。

  • 加号运算符(+)
  • 减号运算符(-)
  • 乘号运算符(*)
  • 除号运算符(/)
1 + 2 // 等于3
5 - 3 // 等于2
2 * 3 // 等于6
10.0 / 2.5 // 等于4.0

Objective-CC语言不一样的是,Swift的算术运算符不容许值超出默认范围。可是你可使用Swift的溢出运算符来进行值溢出的运算。(例:a &+ b),具体请参见溢出运算符
加号运算符一样使用于字符串的拼接:

"hello," + “world” // 等价于hello,world

求余运算符

求余运算符(a%b)是计算b的多少倍恰好能够放下a,而后返回一个多出来的值(也就是求余数)。(好比:4%2 余数为0,3%2 余数为1)。

注意:
求余运算符(%)在其余语言中也就作求模运算符。然而严格来讲,在swift中这个操做符是对于负数来讲的,这里叫作求余比求模更加贴切。

这里给你们讲一下求余运算符是怎么工做的。计算9%4,首先你要计算出4的多少倍可以放得下9

求余运算

你能够发现4的多少倍可以放得下9,余数为1(橘色展现的就是)

在Swift中,求余是这样写的:

9 % 4 // 等于1

为了计算出a%b的值,操做符%用下面的等式来计算并返回了余数做为输出。

a = (b * 倍数) + 余数

倍数是b的一个很大的倍数的时候,可以放的下a

94 带入等式之后:

9 = (4 * 2) + 1

当a的值为负数的时候,计算余数的方法一样适应:

-9 % 4 // 等于1

余数的值为-1
在对b求余的时候,b的符号能够被忽略掉,这就是说a % ba % -b 结果是同样的。

一元负号运算符

数值类型正负能够用在前面加-来进行转换,这就是所谓的一元负号运算符。

let three = 3
let minusThree  = -three// 等价于 -3
let plusThree = -minusThree // 等价于3

一元负号运算符在使用的时候,直接加载常量和变量以后,他们之间不须要添加空格。

一元加号运算符

当一元加号运算符使用的时候,操做符返回的值是他自己,没有发生任何改变。

let minusSix = -6
let  alsoMinusSix = +minusSix
//alsoMinusSix 的值仍为-6

尽管一元加号运算符在使用的时候没有什么实际意义,可是在你使用一元负号来表示负数的时候,能够用一元加号来表示一个正数,这样会使你的代码看起来对称。

组合运算符

和C语言同样,Swift也提供了组合运算符用(=)和其余操做符的组合。下面是一个加号的组合运算符:

var a = 1
a += 2 // 这里a的值为3
print("aa value is \(a)")

表达式a += 2 是表达式a = a + 2的缩写,一个组合加号运算符就是把加号运算和赋值运算符组合成一个,同时完成两个运算任务。

注意:
组合运算符不会返回一个值,例如:你不能这样写:let b = a += 2

关于更多swift标准操做符的问题,请查看运算符声明

比较运算符

Swift支持全部标准的C语言比较符。

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

注意:
Swift也提供了两个操做符 恒等和不恒等(=== and !==)用这两个操做符你能够判断两个对象是否引用同一个实体实例。了解更多请参照类与结构体

每个比表运算符都会返回一个布尔值表示这个表达式是否是对的。

1 == 1 // true 由于1和1 相等
2 != 1 // true 由于2 不等于1
2 > 1 // true 由于2 大于 1
1 < 2 // true 由于1 小于2
1 >= 1 // true 由于1 等于1 知足1 大于等于1
2 <= 1 // false 由于2 小于等于1

比较运算符也常常用在条件语句中,好比说if语句:

let  name = "world"
if name == "world" {
    print("Hello world")
} else {
    print("I'm sorry \(name),but I don't recognize you")
}
// 打印的结果是 Hello world 由于name 等于“world”

更多关于if语句的用法,请参看控制流

若是两个元组的类型相同而且有相同个数的子元素,那么这两个元组能够用来比较。元组从左到右一个值一个值的进行比较,直到发现有两个不一样的值为止。在进行比较的过程当中,若是元组中每一个元素都相同,那么咱们能够说这两个元组相等。例如:

(1,"zebra") < (2,"apple") //返回true 由于1比2小,"zebra"和"apple"是不能被比较的
(3,"apple") < (3,"bird") // 返回true 由于3 等于 3,"apple" 比"bird"少
(4,"dog") < (4,"dog") // 返回true,由于4 等于4 “dog”和“dog”相同。

在上面的这个例子中,你能够看到从左到右的比较行为出如今第一行。由于12小,(1,"zebra")已经被认为比(2,"apple")小了,无论元组的其余值,因此"zebra">"apple"对结果没有影响,由于在比较的时候元组的第一个元素就已经把结果定了。不过当第一个元素相等的时候,就会对第二个第三个元素进行比较了。

当元素的每一个元素都可以用操做符进行比较的时候,咱们能够对元组进行比较。例如:在下面的代码中你能够对两个(String,Int)类型的元组进行比较,由于StringInt均可以用操做符<进行比较。相反,(String,Bool)类型的元组不能用操做符<进行比较,由于Bool不能用操做符<进行比较。

("blue",-1) < ("purple",1)// OK ,返回结果为true
("blue",false) < ("purple",true)//Binary operator '<' cannot be applied to two '(String, Bool)' operands 布尔类型的值不能进行比较(自己比较已是true和false了。。再进行比较,过度了啊)

注意:
Swift标准库里是包含元素小于7个的元组之间的比较的。若是要比较超过7个元素的元组的话,你必须本身实现比较的操做符。

三元运算符

三元运算符是一个特殊的操做符是由三个操做数组成,好比:question?answer1:answer2这种形式。这个是基于questiontrue仍是false的一种表达。若是questiontrue那么它的返回answer1的值,不然,返回answer2的值。

三元运算符的简写以下:

//let  question = true
//let answer1 = "333"
//let answer2 = "333"
//print("the answer is \(question ? answer1:answer2)")
if question {
    answer1
} else {
    answer2
}

这里有一个计算表格行的高度的例子。题意大概是这样的,内容的高度是固定的,当这一行有表头的话高度加50若是没有表头的话加20。

let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50:20)// 结果为90

上面的这个语句是下面的语句的简写:

let contentHeight = 40
let hasHeader = true
let rowHeight:Int
if hasHeader {
    rowHeight = contentHeight + 50
} else {
    rowHeight = contentHeight + 20
}
// rowHeight 结果为90

在第一个例子中,用的是三元操做运算符意味着rowHeight一行低吗就能获得正确的值,这比第二个例子的代码更加简洁。

三元条件运算符提供了一个高效的判断两个参数表达式的标准,须要注意的是,过分的使用三元运算符会使简洁的代码看的不容易懂。咱们应该避免在一个组合的语句中使用多个三元运算符。

合并空值运算符

合并空值运算符(a ?? b)对可选类型a若是包含一个值的时候被打开,或者当a的值为空(nil)的时候返回一个默认的值b。表达式a也是一个可选类型。默认值b的类型必需要和a所存储的值的类型保持一致(也就是说既然ba的默认值,那么b的值的类型就必须和a保持一致,这才是默认值的意义所在,若是a没值那么默认值就顶上来)。

合并空值运算符最简单的代码表达式这样的:

a != nil ? a!  : b

上面的示例代码中使用了三元运算符,当可选类型a不为空的时候,强制打开a(a!),访问a的值,反之,返回默认值b。合并空值运算符提供了一个更加优雅的方式来对条件进行判断和封装,这增长了代码的简洁性和易读性。

注意:
若是a的值是非空的时候,b的值永远不会被使用。这也就是所谓的短路求值。

下面的例子采用的合并空值运算符实现了在默认颜色和可选自定义颜色中进行选择。

let defaultColorName = "red"
var userDefinedColorName: String?//默认值是nil
var colorNameToUse = userDefinedColorName ?? defaultColorName
// 由于userDefinedColorName是nil,因此colorNameToUse被设置为默认值"red"

变量userDefinedColorName定义的是默认值为nil的可选的变量,由于变量userDefinedColorName是可选的类型,所以你可使用合并空值运算符来空值它的值。在上面的例子中,操做符被用来决定一个字符串变量colorNameToUse的默认值。由于userDefinedColorName的值为空,表达式userDefinedColorName ?? defaultColorName返回了defaultColorName也就是"red"

若是你给userDefinedColorName赋一个非空的值,而后让合并空值运算符来检查一下,那么userDefinedColorName的值就会替换掉默认值。

userDefinedColorName = "green"
var colorNameToUse = userDefinedColorName ?? defaultColorName // 由于userDefinedColorName 不为空,因此colorNameToUse的值为"green"。

区间运算符

Swift包含了几个区间运算符,他们表示了一个范围的值的便捷方式。

闭区间运算符

闭区间运算符(a...b)定义了一个只能在ab之间的运行范围,它包括边界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信息,请参看控制流

半开区间运算符

半开区间运算符(a ..< b)定义了一个能在ab之间运行的范围,可是不包括b。也就是说,半开区间包括了它的首值,但不包括尾值(也就是说是半开半闭区间)。和闭区间操做符同样,a的值老是小于b的。若是a的值和b的值相同,那么结果区间就是空的。

当你在处理从0开始的数组的时候,半开运算符显得颇有用,它从0开始遍历到数组的长度(可是不包含数组的长度)。

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(数组的最后一个元素的索引),由于这是半开半闭区间。关于更多数组相关信息,请查看数组

单侧运算符

闭区间有另一种形式让区间朝着一个方向尽量长的延伸。例如:一个包含全部数组元素的区间,从索引为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

逻辑运算符

逻辑运算符的操做对象是逻辑布尔值(true or false),Swift基于C语言的三种逻辑表达式。

  • 逻辑非(!a)
  • 逻辑与(a && b)
  • 逻辑或 (a || b)

逻辑非运算符

逻辑非运算符是对一个布尔值取反,就是让true变成false,让false变成true
逻辑非运算符是一个前置运算符,它每每出如今操做值的前面,不须要添加空格。它能够被读做非a,下面是一个例子:

let  allowedEntry = false
if !allowedEntry {
    print("ACCESS DENIED")
}

//打印结果是ACCESS DENIED

表达语句if !allowedEntry能够被读做“若是不容许进入”。下面一行代码只有在“不容许进入”是true,也就是说只有在allowedEntryfalse的时候执行。

在这个例子中,当心的选择布尔常量和变量有助于咱们保持代码的可读性,而且避免了双重逻辑非运算符,或者混乱的逻辑语句。

逻辑与运算符

逻辑表达式与运算(a && b)表示的是只有等式两边同时为true的时候,才为true,不然就是false
若是有任意一个为false,那么整个表达式就是false。事实上,若是第一个表达式为false的时候,第二个表达式就不执行了,由于这个时候已经不能保证整个表达式是true了,这被称为短路计算。
下面的例子中,只有当两个判断是中的值都为true的时候,if语句才会执行。

let enterDoorCode = true
let passedRetainScan = false
if enterDoorCode && passedRetainScan {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
//打印结果是ACCESS DENIED

逻辑或运算符

逻辑或运算符是由两个内置运算符|组成。你能够用它来表达两个表达式中任意一个为true,那么整个表达式都是true

和上面的逻辑与运算符同样,逻辑运算符或也有一个短路的计算。当左边的表达式的值为true的时候,运算符右边的值就不被计算了,由于不论它是true或者false都不会影响真个表达式的值。

在下面的例子中,第一个布尔值(hasDoorKey)是false,可是第二个值knowsOverridePasswordtrue。由于其中一个值为true,那么整个表达时的值就是true,通道是被容许的。

let hasDoorKey = false
let knowsOverridePassword = true
if hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
//打印结果是Welcome!

混合逻辑运算

你能够把多个逻辑运算符放到一块儿,建立一个混合逻辑表达式。

if enterDoorCode && passedRetainScan || hasDoorKey || passedRetainScan {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
//打印结果是Welcome!

上面的这个例子中使用了多个逻辑运算符&& ||建立了一个混合逻辑运算符。然而,表达式&& ||都只能操做两个值,因此这其实是三个简单的逻辑表达式连续执行的结果,这个例子能够被解读为:

若是咱们输入了正确的密码而且经过了视网膜的扫描,或者咱们有一把有效的钥匙,或者咱们知道怎么在紧急状况下重置密码,那么就被容许进入。

enterDoorCodepassedRetainScan 以及hasDoorKey 由于 enterDoorCode 和 passedRetainScan的值都是false,固逻辑运算符& 值为false 逻辑运算符|| hasDoorKey也为false。可是紧急状况重置密码的权限是true。因此整个混合表达式的值就是true

注意:
swift的逻辑运算符&&||都是左结合式,它意味着混合表达式是由多个逻辑表达式以及计算的。他们在计算的时候优先计算左边的表达式。

显式括号

为了使表达式易读懂,咱们有时候会在合适的地方用括号来包含一个逻辑,固然这个括号多是非必要的。在上个关于门权限的例子中,咱们把第一部分用括号括起来了,这样看起来逻辑更加明确:

if (enterDoorCode && passedRetainScan) || hasDoorKey || knowsOverridePassword {
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
//打印结果是Welcome!

经过这个括号咱们能清楚的看到在整个逻辑表达式中前两个值是逻辑表达式中独立的一部分。虽然最终的输出结果没有变化,可是整个逻辑表达式显得更容易读懂。可读性有时候比简洁性更加剧要,为了使你的代码逻辑更加清晰在合适的地方加上括号吧。

更多swift4.1翻译请查看github

相关文章
相关标签/搜索