zoukankan      html  css  js  c++  java
  • Swift语言指南(九)--基本运算符

    运算符(operator)是用来检查,改变或合并值的一种特殊符号或短语。例如,加号运算符让两个数字相加(如:let i = 1 + 2),还有些更复杂的运算符,如逻辑与运算符(&&)(如:if enteredDoorCode && passedRetinaScan)和自增运算符(++i)(将 i 的值加 1 的便捷写法)。

    Swift 支持标准C语言的大多数运算符,并且改进了一些特性以规避常见的代码错误。赋值运算符(=)是没有返回值的,这样是为了避免在使用等于运算符(==)时误用了赋值运算符(=)。算术运算符(+-*/% 等等)会侦测并阻止值溢出,可避免在运算时超出存储类型的值域范围(比实际运算结果大或小,或不精准--Joe.Huang)。如果需要支持溢出行为,可以选用 Swift 的溢出运算符,详情可见 溢出运算符(后面章节译到)。

    与C语言不同的是,Swift 允许对浮点数求余(%)。Swift 还提供了C语言所没有的两个区间运算符(a..b和a...b),作为表示值域范围的便捷写法。

    本章介绍 Swift 中的常用运算符。高级运算符 (后面章节译到) 一章涵盖了 Swift 中的高级运算符,并讲解了如何自定义运算符,以及让标准运算符支持自定义类型的运算。

    运算符术语

    运算符分为一元,二元,三元运算符:

    · 一元运算符unary operator)对单个目标进行运算(如 -a)。一元运算符前缀unary prefix operator)紧跟运算目标之前(如 !b),而一元运算符后缀unary postfix operator)则紧跟运算目标之后(如 i++)。

    · 二元运算符binary operator)对两个目标进行运算(如 2 + 3),它们属于中缀infix)运算符,因为(运算符号)出现在两个运算目标之间。

    · 三元运算符ternary operator)对三个目标进行运算。与 C 语言一样,Swift 只有一个三元运算符:三元条件运算符( a ? b : c)。

    运算符操作的值称为运算元operands)。在表达式 1 + 2 中,+ 符号是二元运算符,它的两个运算元为值 1与值 2

     

    赋值运算符

    赋值运算符assignment operator,a = b)用 b 的值初始化或更新 a 的值:

    1 let b = 10
    2 var a = 5
    3 a = b
    4 // a is now equal to 10
    5 //a现在等于10

    如果赋值语句的右侧是一个包含多个值的元组,元组的元素可一次性用多个常量或变量分解提取出来(上一章讲解元组时提到过分解元组值的方法--Joe.Huang):

    1 let (x, y) = (1, 2)
    2 // x is equal to 1, and y is equal to 2
    3 //x等于1,y等于2

    与 C 或 Objective-C 语言的赋值运算符不同,Swift 语言的赋值运算符本身没有返回值。因此下面的语句不正确:

    1 if x = y {
    2     // this is not valid, because x = y does not return a value
    3     // 这是无效的,因为 x = y 不会返回一个值 (x==y才可以,--Joe.Huang)
    4 }

    该特性可避免在使用等于运算符(==)时误用了赋值运算符(=)。通过否认 if x = y 的有效性,Swift 将帮助你规避代码中出现这样的错误。

     

    算术运算符

    Swift支持对所有数字类型使用四种标准算术运算符:

    · 加:+

    · 减:-

    · 乘:*

    · 除:/

    1 1 + 2       //  等于3
    2 5 - 3       //  等于2
    3 2 * 3       //  等于6
    4 10.0 / 2.5  //  等于4.0

    与 C / Objective-C 语言的算术运算符不同,Swift 的算术运算符默认不允许值溢出。如果需要支持溢出行为,可以选用 Swift 的溢出运算符(如,a &+ b),详情可见 溢出运算符(后面章节译到)。

    加号运算符也支持 String 拼接:

    "hello, " + "world"  // 等于 "hello, world"

    可以将两个 Character (字符,Unicode字符--Joe.Huang)值相加,或将一个 Character 值与一个 String 值相加,得到新的 String 值:

    1 let dog: Character = ""
    2 let cow: Character = ""
    3 let dogCow = dog + cow
    4 // dogCow 等于 ""

     详见 字符与字符串拼接 (后面章节译到):

    求余运算符

    求余运算符remainder operatora % b)求出 a 包含多少个 b,并返回剩余的值(即整除后的余数 remainder)。

     注:

    求余运算符(%)在其他语言中也称作求模运算符modulo operator)。但对负数的运算结果表明:Swift 语言的实现是严格的求余操作,而非求模操作。

    求余运算符的原理如下。 要计算 9 % 4,首先要求出 9 里面包含多少个 4

     

    如图所示,9 里面包含两个 4,余数是 1 (橙色部分)。 

    Swift中的写法如下:

    9 % 4  //等于 1

    要求出 a % b 的结果,% 运算符会计算下面的等式,并将余数作为输出结果返回:

    a = (b × some multiplier) + remainder

    其中 some multipliera 中能装下 b 的最大数目。

    94 代入等式:

    9 = (4 × 2) + 1

    a 为负数时,求余方法不变:

    -9 % 4   // 等于 -1

    -94 代入等式:

    -9 = (4 × -2) + -1

    得到的余数值为-1

    b 为负值(-b)时,b 的负号将被忽略。因此 a % ba % -b 总是返回相同的结果。

    浮点数的求余计算

    与 C / Objective-C 语言的余数运算符不同,Swift 的余数运算符还能对浮点数进行求余计算:

    8 % 2.5   // equals 0.5

    上例中,8 除以 2.5 等于 3,余数为 0.5,因此余数运算符返回 Double 型的值 0.5

    自增与自减运算符

    与 C 语言类似,Swift 也提供了自增运算符++)与自减运算符--),作为将数字变量的值加上或减去 1 的便捷写法。任何整型或浮点型的变量都可以使用这两个运算符。

    1 var i = 0
    2 ++i      // i 现在等于 1

    每次调用 ++i 时,i 的值就会增加 1。本质上,++i 就是 i = i + 1 的便捷写法。类似地,--i 也相当于 i = i - 1

    ++-- 两对符号可以作为前缀或后缀运算符使用。++ii++ 均可用来将 i 的值加 1。类似地,--i i-- 均可用来将 i 的值减去 1

    注意,这些运算符不仅会改变 i 的值,还会返回一个值。如果你只需要将自增或自减后的值存放在 i 中,那你可以忽略运算符的返回值。但如果你确实要用到返回值,要注意前缀及后缀运算符返回值的差异,规则如下:

    · 如果运算符在变量名前面,先改变它的值,再返回其值。

    · 如果运算符在变量名后面,先返回原值,再改变它的值。

    如例:

    1 var a = 0
    2 let b = ++a
    3 // a 和 b 现在都等于 1,即改变a的值,再返回
    4 let c = a++
    5 // a 现在等于 2, 但 c 还是自增前的值 1,即先返回的a的原值,再改变其值

    在上例中,let b = ++a 先增加 a 的值(加1),然后才返回它的值。因此 ab 都等于新的值 1

    但是,let c = a++ 先返回 a 的原值(加1之前的值)然后才增加 a 的值。即 c 得到了原值 1,然后 a 被更新为新值 2

    除非你需要利用 i++ 的这一特性,建议你在所有情况下都使用 ++i--i,因为它们先修改 i 再返回修改后的值的动作更符合逻辑。

     

    一元减号运算符

    数值前加上前缀 - ,这个前缀运算符 - 就称为一元减号运算符:

    1 let three = 3
    2 let minusThree = -three       // minusThree 等于 -3
    3 let plusThree = -minusThree   // plusThree 等于 3, 或等于 "减去 minusThree"

    一元减号运算符(-)紧靠所要操作的值之前,无需任何空格。

     

    一元加号运算符

    一元加号运算符(+)直接返回所操作的值,不作任何处理:

    1 let minusSix = -6
    2 let alsoMinusSix = +minusSix  // alsoMinusSix 等于 -6

    尽管一元加号运算符实际上不作任何运算,代码中仍然可以用它(提供语义信息,一元减号运算符表示负数,一元加号运算符表示正数--Joe.Huang)与表示负数的一元减号运算符形成对比。

     

    复合赋值运算符

    与 C 语言类似,Swift 也提供复合赋值运算符compound assignment operator将赋值运算符(=)与其他运算组合起来使用。例如加法赋值运算符(addition assignment operator+=):

    1 var a = 1
    2 a += 2
    3 // a 等于 3

    上例中的表达式 a = a + 2 简写为 a += 2,加法和赋值两项操作组合为一个单项操作,执行时非常高效。

    注:

    复合赋值操作没有返回值,即,你不能写:let b = a += 2,这一操作与前面所提到的自增自减操作是不同的。

    复合赋值运算符的完整列表可在 表达式 一章中找到(后面章节译到)。

     

    比较运算符

    Swift支持标准C 的比较运算符:

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

    注:

    Swift还提供了恒等(===)和不恒等(!==)两个鉴别运算符,你可以用它测试两个对象是否引用了同一个对象实例。更多详情请参考 类和结构 一章(后面章节译到)。

    每个比较运算符都会返回一个 Bool 值,检测表达式是否成立:

    1 1 == 1   // true, 因为 1 等于 1
    2 2 != 1   // true, 因为 2 不等于 1
    3 2 > 1    // true, 因为 2 大于 1
    4 1 < 2    // true, 因为 1 小于 2
    5 1 >= 1   // true, 因为 1 大于等于 1
    6 2 <= 1   // false, 因为 2 大于等于 1

    比较运算符常见于条件表达式中,如 if 条件句:

    1 let name = "world"
    2 if name == "world" {
    3     println("hello, world")
    4 } else {
    5     println("I'm sorry (name), but I don't recognize you")
    6     //输出(”对不起
    ame,我不认识你“)
    7 }
    8 // prints "hello, world", because name is indeed equal to "world"
    9 //输出 "hello world",因为 name 确实等于"world"

    if 语句的更多介绍,详见 流程控制 一章(后面章节译到)。

     

    三元条件运算符

    三元运算符是一种特殊运算符,由三个部分组成,表现形式为:question ? answer1 : answer2。它是一种求值简写:根据 question 是否成立,从两个表达式中取出一个并求值。

    如果 question 成立,则计算 answer1 的结果并返回其值;否则计算 answer2 并返回其值。

    三元条件运算符是如下代码的缩写:

    1 if question {
    2     answer1
    3 } else {
    4     answer2
    5 }

    下面的例子将计算表格某行的像素高度。如果该行有表头,则行高应比内容高度高 50 个像素;如果没有表头,则只高出 20 个像素:

    1 let contentHeight = 40
    2 let hasHeader = true
    3 let rowHeight = contentHeight + (hasHeader ? 50 : 20)
    4 // rowHeight(行高) 等于 90

    上例便是如下代码的缩写:

    1 let contentHeight = 40
    2 let hasHeader = true
    3 var rowHeight = contentHeight
    4 if hasHeader {
    5     rowHeight = rowHeight + 50
    6 } else {
    7     rowHeight = rowHeight + 20
    8 }
    9 // rowHeight(行高) 等于 90

    使用三元条件运算符的例子说明,可以仅用一行代码就将行高设为正确的值。这比(不用三元运算符的)第二个例子简洁得多,并且行高(rowHeight)无需定义为变量,因为不再需要用 if 语句修改其值。

    三元条件运算符提供了二选一的高效写法。但使用三元条件运算符应小心。如果过度使用,其简明性可能导致代码可读性差。应避免将多个三元条件运算符组合在同一个语句中。

     

    区间运算符

    Swift有两个区间运算法,是表示值域的简便写法。

     

    闭区间运算符

    区间运算符(a...b)定义了 ab 的区间范围,包括 a 在内。

    闭区间运算符在需要遍历某区间内所有的值时很有用,如在 for-in 循环中使用:

    1 for index in 1...5 {
    2     println("(index) times 5 is (index * 5)")
    3     //输出("(index)乘以 5 得 (index * 5)")
    4 }
    5 // 1 乘以 5 得 5
    6 // 2 乘以 5 得 10
    7 // 3 乘以 5 得 15
    8 // 4 乘以 5 得 20
    9 // 5 乘以 5 得 25

    for-in 语句的更多介绍,详见 流程控制 一章(后面章节译到)。

     

    半闭区间运算符

    半闭区间运算符(a..b)定义了从 ab 的区间,但 b 不包括在内。说它是半闭区间,是因为第一个值包含在区间内,但最后一个值在区间外。

    半闭区间在处理从 0 开始计数的列表时有用,如遍历数组,可从 0 数到列表的长度(但不包括长度值本身):

    1 let names = ["Anna", "Alex", "Brian", "Jack"]
    2 let count = names.count
    3 for i in 0..count {
    4     println("Person (i + 1) is called (names[i])")
    5 }
    6 // Person 1 名字是 Anna
    7 // Person 2 名字是 Alex
    8 // Person 3 名字是 Brian
    9 // Person 4 名字是 Jack

    注意,数组包含四个元素,但因为是半闭区间,所以 0..count 只数到 3(数组中最后一个元素的索引号)。数组更多信息详见 数组 一章(后面章节译到)

     

    逻辑运算符

    逻辑运算符是对布尔逻辑值 truefalse 的组合操作,Swift 支持 C 及其衍生语言的三种标准逻辑运算符:

    · 逻辑非(!a

    · 逻辑与(a && b

    · 逻辑或(a || b

    逻辑非运算符

    逻辑非运算符对布尔值取反,即 true 变成 falsefalse 变成true

    逻辑非运算符是一个前缀运算符,紧跟在所操作值的前面,没有任何空格符。可以理解为"非",如下例:

    1 let allowedEntry = false
    2 if !allowedEntry {
    3     println("ACCESS DENIED")
    4 }
    5 // prints "ACCESS DENIED"
    6 //输出”ACCESS DENIED“

    代码中的 if !allowedEntry 可以理解为“如果不允许进入”。随后的下一行代码仅当“不允许进入”成立时才会执行;即 allowedEntry 为 false 时才执行。

    如上例,布尔值常量及变量的名称应谨慎选择命名,方可确保代码简明又具可读性,同时也应避免使用双重否定或引起混淆的逻辑语句。

     

    逻辑与运算符

    a && b)构造这样的逻辑表达式:运算符两侧的值均为 true,整个表达式的求值结果才为 true

     

    如果有一个值为 false,整个表达式便为 false。事实上,如果第一个值false,第二个值将不执行求值运算,因为无论它为何值,整个表达式的值都不可能等于 true。这也被称为短路求值short-circuit evaluation)。

    下面的例子验证两个值,当两个值都为 true 时才能访问:

     

    1 let enteredDoorCode = true
    2 let passedRetinaScan = false
    3 if enteredDoorCode && passedRetinaScan {
    4     println("Welcome!")
    5 } else {
    6     println("ACCESS DENIED")
    7 }
    8 // prints "ACCESS DENIED"  输出"ACCESS DENIED"

    逻辑或运算符

    a || b)属于中缀运算符,由两个连续的竖线构成。它用来构造这样的表达式:当两个值中有一个为 true时,整个表达式为 true

    与前面的逻辑与运算符一样,逻辑或运算符在检测它的两个表达式时,也使用“短路求值”法。只要逻辑或表达式左侧为 true,其右侧将不执行求值运算,因为这时右侧的值对整个表达式的结果不再有影响。

    下例中,第一个 Bool 值(hasDoorKey)为 false,但第二个值(knowOverridePassword)为 true。因为有一个值为 true,所以整个表达式的求值结果也为 true,因此允许访问:

    1 let hasDoorKey = false
    2 let knowsOverridePassword = true
    3 if hasDoorKey || knowsOverridePassword {
    4     println("Welcome!")
    5 } else {
    6     println("ACCESS DENIED")
    7 }
    8 // prints "Welcome!"  输出"Welcome!"

    组合使用逻辑运算符

    可以将多个逻辑运算符组合起来构成一个较长的复合表达式。

    1if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
    2     println("Welcome!")
    3 } else {
    4     println("ACCESS DENIED")
    5 }
    6 // prints "Welcome!"  输出"Welcome!"

    本例使用多个 &&|| 运算符构成一条较长的复合表达式。不过,&&|| 运算符操作的仍然是两个值,因此该组合表达式实际上是由三个较短的表达式连立而成。它可以这样理解:

    如果我们输入了正确的门禁密码、并且通过了视网膜扫描;或者如果我们有门钥匙;或者如果我们知道紧急的备用密码,则允许访问。

    根据 enteredDoorCodepassedRetinaScanhasDoorKey 三个常量推算,前两个小表达式的值均为 false。不过我们知道紧急的备用密码(knowsOverridePassword 为 true),因此整个复合表达式的求值结果仍然为 true

    
    

    显式括号

    有时(从语法来看)括号并不是必需的,但加上括号却很有用,它可以让复杂表达式的易于阅读。 在上例中,为组合表达式的第一部分加上括号,可使其意图更明显:

    1 if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword {
    2     println("Welcome!")
    3 } else {
    4     println("ACCESS DENIED")
    5 }
    6 // prints "Welcome!"  //输出"Welcome!"

    括号将前两个值与其他值分隔开来,使其作为整体逻辑中的一种可选状态的意思更加明显。组合表达式的结果不会改变,但对读者而言,整体意图更加清晰。可读性总是优先于简洁性;应尽可能在合适的地方使用括号,使你的逻辑更加明晰。

    谢谢,Swifter-QQ群:362232993,同好者进~ 

    Fork:https://github.com/Joejo/Swift-lesson-for-chinese

  • 相关阅读:
    部署 AppGlobalResources 到 SharePoint 2010
    还原一个已删除的网站集
    使用仪表板设计器配置级联筛选器 (SharePoint Server 2010 SP1)
    File or arguments not valid for site template
    Pex and Moles Documentation
    Content Query Webpart匿名访问
    Running Moles using NUnit Console from Visual Studio
    Calling a WCF Service using jQuery in SharePoint the correct way
    Updating Content Types and Site Columns That Were Deployed as a Feature
    asp.net中判断传过来的字符串不为空的代码
  • 原文地址:https://www.cnblogs.com/joejs/p/3789704.html
Copyright © 2011-2022 走看看