基础运算符(Basic Operators)

    运算符是一个特殊的符号或者短句,你可以用它来检查,改变或者组合某一些值。比如,加法运算符(+)可以让2个数字相加,像在 let i = 1 + 2 中一样,有比如逻辑与运算符(&&),可以组合2个布尔值,就像在 if  true && false 中一样。

    Swfit支持大多数标准c语言中的运算符,还改善了部分功能,用以排除一些常见的编码错误。赋值运算符(=)不会有返回值,防止和比较运算符(==)混用。术数运算符(+,-*,/,%等),会检测并防止值溢出。避免在正在处理的值不在对应类型可以存储的值的范围之中而出现意料之外的结果。你可以选择溢出运算符来选择值溢出是采取的行为。

    Swift也提供了C语言中没有的范围运算符,比如a..<ba...b,这是表示值的范围的简写。

    这一章只描述Swift中常用的运算符。在高级运算符章节中,会覆盖Swift的高级运算符,以及如何定义你自己的运算符,或者为你自定义的类实现标准库中的运算符。

术语(Terminology)

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

    一元运算符作用在一个单独的目标上,比如(-a)。一元的前缀运算符紧跟在要操作的目标之前(!b)。一元的后缀运算符紧跟在要操作的目标之后(c!)。

    二元运算符作用在2个目标上,比如2 + 3。被称为中缀,因为它出现在2个目标之间。

    三元运算符作用在3个目标之上。和C语言一样,Swift只有一个三元运算符,也就是三目运算符(a ? b : c)

    运算符操作的值叫做运算单元。在表达式1 + 2中,+ 号运算符是一个2元运算符,它的2个运算单元是值1和2。


赋值运算符(Assignment Operator)

    赋值运算符(a = b)用来使用b的值初始化或者更新a的值。

        let b = 10

        var a = 5

        a = b

        // a 现在等于 10

    如果赋值运算符右边是一个包含了多个值的元组,它的元素可以通过一次操作分出多个常量或者变量。

        let (x, y) = (1, 2)         // x 等于 1, y 等于 2”

    和C语言以及OC中不一样,Swift中的赋值运算符本身不会有返回值,所以下面的语句是无效的:

        if x = y { 

            // 无效, 因为 x = y 没有返回值.

        }

    这种特性可以防止赋值运算符和相等比较运算符(==)之间的误用。通过是if x = y 无效,Swift可以防止在你的代码中出现错误。


术数运算符(Arithmetic Operators)

    Swift为所有数字类型支持了4个基本的术数运算符:

        加法运算符(+)    1 + 2      // 3

        减法运算符(-)     5 - 3     // 2

        乘法运算符(*)     2 * 3     // 6

        除法运算符(/)      10.0 / 2.5     // 4.0

    和C语言和OC中的术数运算运算符不一样,Swift中的术数运算符默认不允许值溢出。可以使用Swift中值溢出运算符来选择值溢出的行为。

    加法运算符也要支持字符串的连接:

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

  取余运算符(Remainder Operator)

    取余运算符(a % b)计算出a里面可以包含多少个b,然后返回剩下的值,也就是余数。

NOTE:取余运算符(%)在其他语言中也被称为模运算符。然而严格来说,它是一个取余操作而不是取模操作。

    9里面有2个4,所以余数是1。在Swift中,可以写成: 9 % 4

    取余运算符使用下面的等式并且返回余数作为输出,来决定 a % b 的结果:

        a = (b x someMultiplier) + remainder

    其中someMultipliera中可以有的最大的b的个数,把9和4代入这个等式:

        9 = (4 x 2) + 1

    计算负数的时候使用的是同样的计算公式:

        -9 % 4     // -1 

    把-94插入到上述的等式中:

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

    可以得到余数的值是-1

    在公式中负数 b 的符号会被忽略。这就意味着 a % ba % -b 的结果总是一样的。

一元减法运算符(-)

    数值可以使用前缀(-),也就是一元减法运算符:

        let three = 3

        let minusThree = -three           //  -3

        let plusThree = -minusThree   // 3

    一元减法运算符需要直接添加在需要操作的值前面,不需要有空格。

一元加法运算符(+)

    一元加法运算符直接返回它操作的值,不做任何改变:

        let minusSix = -6

        let alsoMinusSix = +minusSix  // -6

    虽然一元加法运算符并不做任何事情,但是你可以在一些使用了一元减法运算符的代码中使用一元加法运算符来保持代码的对称。

符合赋值运算符(Compound Assignment Operators)

    和C语言一样,Swift提供了混合赋值运算符,也就是赋值运算符和其他运算符组合使用。一个例子就是加法混合运算符(+=):

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

    表达式 a += 2 a = a + 2 的简写。为了更高的效率,加法运算符和复制运算符被组合在成一个运算符,一次执行了2个任务。

NOTE:混合运算符没有返回值,比如, let b = a += 2 是不对的。

比较运算符

    Swift提供了标准C语言所有的比较运算符:

        等于 (a == b)                     不等于 (a != b)

        大于 (a > b)                        小于 (a < b)

        大于等于 to (a >= b)         小于等于 (a <= b)

NOTE:Swift还提供了2个恒等运算符(===和!==),可以用来测试2个对象的引用是不是引用于同一个对象的实例。

    每一个比较运算符返回一个布尔值来表明表达式是不是成立。

    比较运算符通常会用在条件语句中,比如if语句:

        let name = "world"

        if name == "world" {

            print("hello, world")

        } else {

            print("I'm sorry \(name), but I don't recognize you")

        }

        // 打印 "hello, world", because name 等于 "world"

    如果2个元组有相同的类型,也可以用比较运算符比较。元组从左至右进行比较,一次比较一个值,直到比较结果不相等。两个对应的值的比较,会决定整个元祖的比较的结果。如果所有的元素都相等,那么元祖就是相等的,比如:

        (1, "zebra") < (2, "apple") // true 因为 1 小于 2 ,后面的不比较

        (3, "apple") < (3, "bird")    // true  因为3 等于 3, "apple" 小于 "bird"

        (4, "dog") == (4, "dog")      // true 因为 4 等于 4, and "dog" 等于 "dog”

    上面的例子中,可以看见第一行从左往右进行比较,因为1小于2,元组(1, "zebra")就被认为小于元组(2, "apple"),无论元组中的其他值是什么。不会去考虑"zebra"并不小于"apple",因为第一个元素的的比较已经决定了比较结果。然而,当第一个元素比较结果相等的话,第二个元素就会被拿来比较,第二行和第三行就是这样子做的。

    只有在运算符适用于元祖的每一个元素,元组才可以比较。比如下面的例子,可以比较 (String, Int)类型的元组,因为String和Int都可以用 < 运算符比较。相对的,(String, Bool)类型的元组就不可以用 < 运算符比较,因为布尔值不可以使用< 运算符。

        ("blue", -1) < ("purple", 1)  // OK, evaluates to true

        ("blue", false) < ("purple", true)  // 错误,小于运算符不适用于布尔值

NOTE:Swift标准库实现的元祖比较符只支持元素个数小于7个的元素。如果希望比较7个或者更多的元素的元组,你需要自己实现比较运算符。

三元条件运算符(Ternary Conditional Operator)

    三元条件运算符是一个包括了三个部分的特殊的元素的特殊的运算符,就像这样: question ? answer1 : answer2

    这是一种简洁代码的方式,它根据question的结果去决定是执行answer1还是answer2,如果question的结果是true,会执行并返回answer1的返回值,如果question的结果是false,会执行并返回answer2的返回值。

    三元条件运算符是下面代码的简写:

        if question {

            answer1

        } else {

            answer2

        }

    在有2个表达式需要考虑的情况下,三木运算提供了非常有效的简写方式。然而,请谨慎使用三木运算,它很简洁,但是过度使用付出的代价是难以阅读。在一些混合语句中尽量避免使用三木运算。

空合运算符(Nil-Coalescing Operator)

    空合运算符(a ?? b),如果可选值a有值,解包a并且返回a解包后的值,如果a没有值,返回默认值b。表达式中的a是一个可选值,ba解包后的值的类型一样。

    空合运算符下面代码的简写:

        a  !=  nil ? a! : b   // ( a  !=  nil)中  != 是一个整体,  而不是 a!是一个整体!!

    上面的代码使用了三目运算符和强制解包去访问a中包含的值,当a是nil的时候就返回b。空合运算符以一种优雅的方式,使得条件判断和解包的操作可以用更精简和易读的形式组合在了一起。

NOTE:如果a的值不是nil,b的值不会被求值。也就是所谓的短路求值。

    下面的例子使用空合运算符在默认的颜色和用户定义的颜色之间做选择:

        let defaultColorName = "red"

        var userDefinedColorName: String?  // 默认是nil

        var colorNameToUse = userDefinedColorName ?? defaultColorName

        // userDefinedColorName is nil, 所以使用默认值 defaultColorName  "red"

    变量userDefinedColorName被定义为可选的String类型,默认是nil。因为userDefinedColorName是可选值,所以可以在考虑它的值的时候使用空合运算。上面的例子中,空合运算是为了决定变量colorNameToUse的初始值,因为userDefinedColorName是nil,表示式userDefinedColorName ?? defaultColorName返回defaultColorName的值,也就是"red"。

    如果给可选变量userDefinedColorName赋予一个非空的值,然后再执行空合运算,将不会返回默认值,而是返回userDefinedColorName中包含的值。

        userDefinedColorName = "green"

        colorNameToUse = userDefinedColorName ?? defaultColorName

        // userDefinedColorName 不是 nil, 所以colorNameToUse现在是"green"

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容