在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ iOS/ 高級(jí)運(yùn)算符
方法 - Methods
關(guān)于 Swift
下標(biāo)腳本(Subscripts)
類和結(jié)構(gòu)體
類型轉(zhuǎn)換(Type Casting)
控制流
析構(gòu)過(guò)程(Deinitialization)
集合類型 (Collection Types)
構(gòu)造過(guò)程(Initialization)
Optional Chaining
枚舉(Enumerations)
自動(dòng)引用計(jì)數(shù)
繼承(Inheritance)
擴(kuò)展(Extensions)
泛型
字符串和字符(Strings and Characters)
函數(shù)(Functions)
高級(jí)運(yùn)算符
訪問(wèn)控制
基本運(yùn)算符
嵌套類型
閉包(Closures)
協(xié)議
屬性 (Properties)

高級(jí)運(yùn)算符

除了基本操作符中所講的運(yùn)算符,Swift還有許多復(fù)雜的高級(jí)運(yùn)算符,包括了C語(yǔ)言和Objective-C中的位運(yùn)算符和移位運(yùn)算。

不同于C語(yǔ)言中的數(shù)值計(jì)算,Swift的數(shù)值計(jì)算默認(rèn)是不可溢出的。溢出行為會(huì)被捕獲并報(bào)告為錯(cuò)誤。你是故意的?好吧,你可以使用Swift為你準(zhǔn)備的另一套默認(rèn)允許溢出的數(shù)值運(yùn)算符,如可溢出的加號(hào)為&+。所有允許溢出的運(yùn)算符都是以&開始的。

自定義的結(jié)構(gòu),類和枚舉,是否可以使用標(biāo)準(zhǔn)的運(yùn)算符來(lái)定義操作?當(dāng)然可以!在Swift中,你可以為你創(chuàng)建的所有類型定制運(yùn)算符的操作。

可定制的運(yùn)算符并不限于那些預(yù)設(shè)的運(yùn)算符,你可以自定義中置,前置,后置及賦值運(yùn)算符,當(dāng)然還有優(yōu)先級(jí)和結(jié)合性。這些運(yùn)算符在代碼中可以像預(yù)設(shè)的運(yùn)算符一樣使用,你也可以擴(kuò)展已有的類型以支持你自定義的運(yùn)算符。

位運(yùn)算符

位操作符可以操作數(shù)據(jù)結(jié)構(gòu)中原始數(shù)據(jù)的每個(gè)比特位。位操作符通常在諸如圖像處理和創(chuàng)建設(shè)備驅(qū)動(dòng)等底層開發(fā)中使用,位操作符在同外部資源的數(shù)據(jù)進(jìn)行交互的時(shí)候也很有用,比如在使用用戶協(xié)議進(jìn)行通信的時(shí)候,運(yùn)用位運(yùn)算符來(lái)對(duì)原始數(shù)據(jù)進(jìn)行編碼和解碼。

Swift支持如下所有C語(yǔ)言的位運(yùn)算符:

按位取反運(yùn)算符

按位取反運(yùn)算符~對(duì)一個(gè)操作數(shù)的每一位都取反。

http://wiki.jikexueyuan.com/project/swift-language-guide/images/Advanced_Operators_1.png" alt="Image of Advanced_Operators_1.png" />

這個(gè)運(yùn)算符是前置的,所以請(qǐng)不加任何空格地寫在操作數(shù)之前。

    let initialBits: UInt8 = 0b00001111
    let invertedBits = ~initialBits  // 等于 0b11110000

UInt8是8位無(wú)符整型,可以存儲(chǔ)0~255之間的任意數(shù)。這個(gè)例子初始化一個(gè)整型為二進(jìn)制值00001111(前4位為0,后4位為1),它的十進(jìn)制值為15

使用按位取反運(yùn)算~對(duì)initialBits操作,然后賦值給invertedBits這個(gè)新常量。這個(gè)新常量的值等于所有位都取反的initialBits,即1變成00變成1,變成了11110000,十進(jìn)制值為240

按位與運(yùn)算符

按位與運(yùn)算符對(duì)兩個(gè)數(shù)進(jìn)行操作,然后返回一個(gè)新的數(shù),這個(gè)數(shù)的每個(gè)位都需要兩個(gè)輸入數(shù)的同一位都為1時(shí)才為1。

http://wiki.jikexueyuan.com/project/swift-language-guide/images/Advanced_Operators_2.png" alt="Image of Advanced_Operators_2.png" />

以下代碼,firstSixBitslastSixBits中間4個(gè)位都為1。對(duì)它倆進(jìn)行按位與運(yùn)算后,就得到了00111100,即十進(jìn)制的60。

    let firstSixBits: UInt8 = 0b11111100
    let lastSixBits: UInt8  = 0b00111111
    let middleFourBits = firstSixBits & lastSixBits  // 等于 00111100

按位或運(yùn)算

按位或運(yùn)算符|比較兩個(gè)數(shù),然后返回一個(gè)新的數(shù),這個(gè)數(shù)的每一位設(shè)置1的條件是兩個(gè)輸入數(shù)的同一位都不為0(即任意一個(gè)為1,或都為1)。

http://wiki.jikexueyuan.com/project/swift-language-guide/images/Advanced_Operators_3.png" alt="Image of Advanced_Operators_3.png" />

如下代碼,someBitsmoreBits在不同位上有1。按位或運(yùn)行的結(jié)果是11111110,即十進(jìn)制的254。

    let someBits: UInt8 = 0b10110010
    let moreBits: UInt8 = 0b01011110
    let combinedbits = someBits | moreBits  // 等于 11111110

按位異或運(yùn)算符

按位異或運(yùn)算符^比較兩個(gè)數(shù),然后返回一個(gè)數(shù),這個(gè)數(shù)的每個(gè)位設(shè)為1的條件是兩個(gè)輸入數(shù)的同一位不同,如果相同就設(shè)為0

http://wiki.jikexueyuan.com/project/swift-language-guide/images/Advanced_Operators_4.png" alt="Image of Advanced_Operators_4.png" />

以下代碼,firstBitsotherBits都有一個(gè)1跟另一個(gè)數(shù)不同的。所以按位異或的結(jié)果是把它這些位置為1,其他都置為0

    let firstBits: UInt8 = 0b00010100
    let otherBits: UInt8 = 0b00000101
    let outputBits = firstBits ^ otherBits  // 等于 00010001

按位左移/右移運(yùn)算符

左移運(yùn)算符<<和右移運(yùn)算符>>會(huì)把一個(gè)數(shù)的所有比特位按以下定義的規(guī)則向左或向右移動(dòng)指定位數(shù)。

按位左移和按位右移的效果相當(dāng)把一個(gè)整數(shù)乘于或除于一個(gè)因子為2的整數(shù)。向左移動(dòng)一個(gè)整型的比特位相當(dāng)于把這個(gè)數(shù)乘于2,向右移一位就是除于2

無(wú)符整型的移位操作

對(duì)無(wú)符整型的移位的效果如下:

已經(jīng)存在的比特位向左或向右移動(dòng)指定的位數(shù)。被移出整型存儲(chǔ)邊界的的位數(shù)直接拋棄,移動(dòng)留下的空白位用零0來(lái)填充。這種方法稱為邏輯移位。

以下這張把展示了 11111111 << 1(11111111向左移1位),和 11111111 >> 1(11111111向右移1位)。藍(lán)色的是被移位的,灰色是被拋棄的,橙色的0是被填充進(jìn)來(lái)的。

http://wiki.jikexueyuan.com/project/swift-language-guide/images/Advanced_Operators_5.png" alt="Image of Advanced_Operators_5.png" />

    let shiftBits: UInt8 = 4   // 即二進(jìn)制的00000100
    shiftBits << 1             // 00001000
    shiftBits << 2             // 00010000
    shiftBits << 5             // 10000000
    shiftBits << 6             // 00000000
    shiftBits >> 2             // 00000001

你可以使用移位操作進(jìn)行其他數(shù)據(jù)類型的編碼和解碼。

    let pink: UInt32 = 0xCC6699
    let redComponent = (pink & 0xFF0000) >> 16    // redComponent 是 0xCC, 即 204
    let greenComponent = (pink & 0x00FF00) >> 8   // greenComponent 是 0x66, 即 102
    let blueComponent = pink & 0x0000FF           // blueComponent 是 0x99, 即 153

這個(gè)例子使用了一個(gè)UInt32的命名為pink的常量來(lái)存儲(chǔ)層疊樣式表CSS中粉色的顏色值,CSS顏色#CC6699在Swift用十六進(jìn)制0xCC6699來(lái)表示。然后使用按位與(&)和按位右移就可以從這個(gè)顏色值中解析出紅(CC),綠(66),藍(lán)(99)三個(gè)部分。

對(duì)0xCC66990xFF0000進(jìn)行按位與&操作就可以得到紅色部分。0xFF0000中的0了遮蓋了OxCC6699的第二和第三個(gè)字節(jié),這樣6699被忽略了,只留下0xCC0000。

然后,按向右移動(dòng)16位,即 >> 16。十六進(jìn)制中每?jī)蓚€(gè)字符是8比特位,所以移動(dòng)16位的結(jié)果是把0xCC0000變成0x0000CC。這和0xCC是相等的,就是十進(jìn)制的204。

同樣的,綠色部分來(lái)自于0xCC66990x00FF00的按位操作得到0x006600。然后向右移動(dòng)8位,得到0x66,即十進(jìn)制的102

最后,藍(lán)色部分對(duì)0xCC66990x0000FF進(jìn)行按位與運(yùn)算,得到0x000099,無(wú)需向右移位了,所以結(jié)果就是0x99,即十進(jìn)制的153。

有符整型的移位操作

有符整型的移位操作相對(duì)復(fù)雜得多,因?yàn)檎?fù)號(hào)也是用二進(jìn)制位表示的。(這里舉的例子雖然都是8位的,但它的原理是通用的。)

有符整型通過(guò)第1個(gè)比特位(稱為符號(hào)位)來(lái)表達(dá)這個(gè)整數(shù)是正數(shù)還是負(fù)數(shù)。0代表正數(shù),1代表負(fù)數(shù)。

其余的比特位(稱為數(shù)值位)存儲(chǔ)其實(shí)值。有符正整數(shù)和無(wú)符正整數(shù)在計(jì)算機(jī)里的存儲(chǔ)結(jié)果是一樣的,下來(lái)我們來(lái)看+4內(nèi)部的二進(jìn)制結(jié)構(gòu)。

http://wiki.jikexueyuan.com/project/swift-language-guide/images/Advanced_Operators_6.png" alt="Image of Advanced_Operators_6.png" />

符號(hào)位為0,代表正數(shù),另外7比特位二進(jìn)制表示的實(shí)際值就剛好是4。

負(fù)數(shù)呢,跟正數(shù)不同。負(fù)數(shù)存儲(chǔ)的是2的n次方減去它的絕對(duì)值,n為數(shù)值位的位數(shù)。一個(gè)8比特的數(shù)有7個(gè)數(shù)值位,所以是2的7次方,即128。

我們來(lái)看-4存儲(chǔ)的二進(jìn)制結(jié)構(gòu)。

http://wiki.jikexueyuan.com/project/swift-language-guide/images/Advanced_Operators_7.png" alt="Image of Advanced_Operators_7.png" />

現(xiàn)在符號(hào)位為1,代表負(fù)數(shù),7個(gè)數(shù)值位要表達(dá)的二進(jìn)制值是124,即128 - 4。

http://wiki.jikexueyuan.com/project/swift-language-guide/images/Advanced_Operators_8.png" alt="Image of Advanced_Operators_8.png" />

負(fù)數(shù)的編碼方式稱為二進(jìn)制補(bǔ)碼表示。這種表示方式看起來(lái)很奇怪,但它有幾個(gè)優(yōu)點(diǎn)。

首先,只需要對(duì)全部8個(gè)比特位(包括符號(hào))做標(biāo)準(zhǔn)的二進(jìn)制加法就可以完成 -1 + -4 的操作,忽略加法過(guò)程產(chǎn)生的超過(guò)8個(gè)比特位表達(dá)的任何信息。

http://wiki.jikexueyuan.com/project/swift-language-guide/images/Advanced_Operators_9.png" alt="Image of Advanced_Operators_9.png" />

第二,由于使用二進(jìn)制補(bǔ)碼表示,我們可以和正數(shù)一樣對(duì)負(fù)數(shù)進(jìn)行按位左移右移的,同樣也是左移1位時(shí)乘于2,右移1位時(shí)除于2。要達(dá)到此目的,對(duì)有符整型的右移有一個(gè)特別的要求:

對(duì)有符整型按位右移時(shí),不使用0填充空白位,而是根據(jù)符號(hào)位(正數(shù)為0,負(fù)數(shù)為1)填充空白位。

http://wiki.jikexueyuan.com/project/swift-language-guide/images/Advanced_Operators_10.png" alt="Image of Advanced_Operators_10.png" />

這就確保了在右移的過(guò)程中,有符整型的符號(hào)不會(huì)發(fā)生變化。這稱為算術(shù)移位。

正因?yàn)檎龜?shù)和負(fù)數(shù)特殊的存儲(chǔ)方式,向右移位使它接近于0。移位過(guò)程中保持符號(hào)會(huì)不變,負(fù)數(shù)在接近0的過(guò)程中一直是負(fù)數(shù)。

溢出運(yùn)算符

默認(rèn)情況下,當(dāng)你往一個(gè)整型常量或變量賦于一個(gè)它不能承載的大數(shù)時(shí),Swift不會(huì)讓你這么干的,它會(huì)報(bào)錯(cuò)。這樣,在操作過(guò)大或過(guò)小的數(shù)的時(shí)候就很安全了。

例如,Int16整型能承載的整數(shù)范圍是-3276832767,如果給它賦上超過(guò)這個(gè)范圍的數(shù),就會(huì)報(bào)錯(cuò):

    var potentialOverflow = Int16.max
    // potentialOverflow 等于 32767, 這是 Int16 能承載的最大整數(shù)
    potentialOverflow += 1
    // 噢, 出錯(cuò)了

對(duì)過(guò)大或過(guò)小的數(shù)值進(jìn)行錯(cuò)誤處理讓你的數(shù)值邊界條件更靈活。

當(dāng)然,你有意在溢出時(shí)對(duì)有效位進(jìn)行截?cái)?,你可采用溢出運(yùn)算,而非錯(cuò)誤處理。Swfit為整型計(jì)算提供了5個(gè)&符號(hào)開頭的溢出運(yùn)算符。

  • 溢出加法 &+
  • 溢出減法 &-
  • 溢出乘法 &*
  • 溢出除法 &/
  • 溢出求余 &%

值的上溢出

下面例子使用了溢出加法&+來(lái)解剖的無(wú)符整數(shù)的上溢出

    var willOverflow = UInt8.max
    // willOverflow 等于UInt8的最大整數(shù) 255
    willOverflow = willOverflow &+ 1
    // 此時(shí) willOverflow 等于 0

willOverflowInt8所能承載的最大值255(二進(jìn)制11111111),然后用&+加1。然后UInt8就無(wú)法表達(dá)這個(gè)新值的二進(jìn)制了,也就導(dǎo)致了這個(gè)新值上溢出了,大家可以看下圖。溢出后,新值在UInt8的承載范圍內(nèi)的那部分是00000000,也就是0。

http://wiki.jikexueyuan.com/project/swift-language-guide/images/Advanced_Operators_11.png" alt="Image of Advanced_Operators_11.png" />

值的下溢出

數(shù)值也有可能因?yàn)樘《浇?。舉個(gè)例子:

UInt8的最小值是0(二進(jìn)制為00000000)。使用&-進(jìn)行溢出減1,就會(huì)得到二進(jìn)制的11111111即十進(jìn)制的255

http://wiki.jikexueyuan.com/project/swift-language-guide/images/Advanced_Operators_12.png" alt="Image of Advanced_Operators_12.png" />

Swift代碼是這樣的:

    var willUnderflow = UInt8.min
    // willUnderflow 等于UInt8的最小值0
    willUnderflow = willUnderflow &- 1
    // 此時(shí) willUnderflow 等于 255

有符整型也有類似的下溢出,有符整型所有的減法也都是對(duì)包括在符號(hào)位在內(nèi)的二進(jìn)制數(shù)進(jìn)行二進(jìn)制減法的,這在 "按位左移/右移運(yùn)算符" 一節(jié)提到過(guò)。最小的有符整數(shù)是-128,即二進(jìn)制的10000000。用溢出減法減去去1后,變成了01111111,即UInt8所能承載的最大整數(shù)127

http://wiki.jikexueyuan.com/project/swift-language-guide/images/Advanced_Operators_13.png" alt="Image of Advanced_Operators_13.png" />

來(lái)看看Swift代碼:

    var signedUnderflow = Int8.min
    // signedUnderflow 等于最小的有符整數(shù) -128
    signedUnderflow = signedUnderflow &- 1
    // 此時(shí) signedUnderflow 等于 127

除零溢出

一個(gè)數(shù)除以0 i / 0,或者對(duì)0求余數(shù) i % 0,就會(huì)產(chǎn)生一個(gè)錯(cuò)誤。

    let x = 1
    let y = x / 0

使用它們對(duì)應(yīng)的可溢出的版本的運(yùn)算符&/&%進(jìn)行除0操作時(shí)就會(huì)得到0值。

    let x = 1
    let y = x &/ 0
    // y 等于 0

優(yōu)先級(jí)和結(jié)合性

運(yùn)算符的優(yōu)先級(jí)使得一些運(yùn)算符優(yōu)先于其他運(yùn)算符,高優(yōu)先級(jí)的運(yùn)算符會(huì)先被計(jì)算。

結(jié)合性定義相同優(yōu)先級(jí)的運(yùn)算符在一起時(shí)是怎么組合或關(guān)聯(lián)的,是和左邊的一組呢,還是和右邊的一組。意思就是,到底是和左邊的表達(dá)式結(jié)合呢,還是和右邊的表達(dá)式結(jié)合?

在混合表達(dá)式中,運(yùn)算符的優(yōu)先級(jí)和結(jié)合性是非常重要的。舉個(gè)例子,為什么下列表達(dá)式的結(jié)果為4?

    2 + 3 * 4 % 5
    // 結(jié)果是 4

如果嚴(yán)格地從左計(jì)算到右,計(jì)算過(guò)程會(huì)是這樣:

  • 2 + 3 = 5
  • 5 * 4 = 20
  • 20 / 5 = 4 余 0

但是正確答案是4而不是0。優(yōu)先級(jí)高的運(yùn)算符要先計(jì)算,在Swift和C語(yǔ)言中,都是先乘除后加減的。所以,執(zhí)行完乘法和求余運(yùn)算才能執(zhí)行加減運(yùn)算。

乘法和求余擁有相同的優(yōu)先級(jí),在運(yùn)算過(guò)程中,我們還需要結(jié)合性,乘法和求余運(yùn)算都是左結(jié)合的。這相當(dāng)于在表達(dá)式中有隱藏的括號(hào)讓運(yùn)算從左開始。

    2 + ((3 * 4) % 5)

3 * 4 = 12,所以這相當(dāng)于:

    2 + (12 % 5)

12 % 5 = 2,所這又相當(dāng)于

    2 + 2

計(jì)算結(jié)果為 4。

查閱Swift運(yùn)算符的優(yōu)先級(jí)和結(jié)合性的完整列表,請(qǐng)看表達(dá)式。

注意:
Swift的運(yùn)算符較C語(yǔ)言和Objective-C來(lái)得更簡(jiǎn)單和保守,這意味著跟基于C的語(yǔ)言可能不一樣。所以,在移植已有代碼到Swift時(shí),注意去確保代碼按你想的那樣去執(zhí)行。

運(yùn)算符函數(shù)

讓已有的運(yùn)算符也可以對(duì)自定義的類和結(jié)構(gòu)進(jìn)行運(yùn)算,這稱為運(yùn)算符重載。

這個(gè)例子展示了如何用+讓一個(gè)自定義的結(jié)構(gòu)做加法。算術(shù)運(yùn)算符+是一個(gè)兩目運(yùn)算符,因?yàn)樗袃蓚€(gè)操作數(shù),而且它必須出現(xiàn)在兩個(gè)操作數(shù)之間。

例子中定義了一個(gè)名為Vector2D的二維坐標(biāo)向量 (x,y) 的結(jié)構(gòu),然后定義了讓兩個(gè)Vector2D的對(duì)象相加的運(yùn)算符函數(shù)。

    struct Vector2D {
        var x = 0.0, y = 0.0
    }
    @infix func + (left: Vector2D, right: Vector2D) -> Vector2D {
        return Vector2D(x: left.x + right.x, y: left.y + right.y)
    }

該運(yùn)算符函數(shù)定義了一個(gè)全局的+函數(shù),這個(gè)函數(shù)需要兩個(gè)Vector2D類型的參數(shù),返回值也是Vector2D類型。需要定義和實(shí)現(xiàn)一個(gè)中置運(yùn)算的時(shí)候,在關(guān)鍵字func之前寫上屬性 @infix 就可以了。

在這個(gè)代碼實(shí)現(xiàn)中,參數(shù)被命名為了leftright,代表+左邊和右邊的兩個(gè)Vector2D對(duì)象。函數(shù)返回了一個(gè)新的Vector2D的對(duì)象,這個(gè)對(duì)象的xy分別等于兩個(gè)參數(shù)對(duì)象的xy的和。

這個(gè)函數(shù)是全局的,而不是Vector2D結(jié)構(gòu)的成員方法,所以任意兩個(gè)Vector2D對(duì)象都可以使用這個(gè)中置運(yùn)算符。

    let vector = Vector2D(x: 3.0, y: 1.0)
    let anotherVector = Vector2D(x: 2.0, y: 4.0)
    let combinedVector = vector + anotherVector
    // combinedVector 是一個(gè)新的Vector2D, 值為 (5.0, 5.0)

這個(gè)例子實(shí)現(xiàn)兩個(gè)向量 (3.0,1.0)(2.0,4.0) 相加,得到向量 (5.0,5.0) 的過(guò)程。如下圖示:

http://wiki.jikexueyuan.com/project/swift-language-guide/images/Advanced_Operators_14.png" alt="Image of Advanced_Operators_14.png" />

前置和后置運(yùn)算符

上個(gè)例子演示了一個(gè)雙目中置運(yùn)算符的自定義實(shí)現(xiàn),同樣我們也可以玩標(biāo)準(zhǔn)單目運(yùn)算符的實(shí)現(xiàn)。單目運(yùn)算符只有一個(gè)操作數(shù),在操作數(shù)之前就是前置的,如-a; 在操作數(shù)之后就是后置的,如i++。

實(shí)現(xiàn)一個(gè)前置或后置運(yùn)算符時(shí),在定義該運(yùn)算符的時(shí)候于關(guān)鍵字func之前標(biāo)注 @prefix@postfix 屬性。

    @prefix func - (vector: Vector2D) -> Vector2D {
        return Vector2D(x: -vector.x, y: -vector.y)
    }

這段代碼為Vector2D類型提供了單目減運(yùn)算-a,@prefix屬性表明這是個(gè)前置運(yùn)算符。

對(duì)于數(shù)值,單目減運(yùn)算符可以把正數(shù)變負(fù)數(shù),把負(fù)數(shù)變正數(shù)。對(duì)于Vector2D,單目減運(yùn)算將其xy都進(jìn)進(jìn)行單目減運(yùn)算。

    let positive = Vector2D(x: 3.0, y: 4.0)
    let negative = -positive
    // negative 為 (-3.0, -4.0)
    let alsoPositive = -negative
    // alsoPositive 為 (3.0, 4.0)

組合賦值運(yùn)算符

組合賦值是其他運(yùn)算符和賦值運(yùn)算符一起執(zhí)行的運(yùn)算。如+=把加運(yùn)算和賦值運(yùn)算組合成一個(gè)操作。實(shí)現(xiàn)一個(gè)組合賦值符號(hào)需要使用@assignment屬性,還需要把運(yùn)算符的左參數(shù)設(shè)置成inout,因?yàn)檫@個(gè)參數(shù)會(huì)在運(yùn)算符函數(shù)內(nèi)直接修改它的值。

    @assignment func += (inout left: Vector2D, right: Vector2D) {
        left = left + right
    }

因?yàn)榧臃ㄟ\(yùn)算在之前定義過(guò)了,這里無(wú)需重新定義。所以,加賦運(yùn)算符函數(shù)使用已經(jīng)存在的高級(jí)加法運(yùn)算符函數(shù)來(lái)執(zhí)行左值加右值的運(yùn)算。

    var original = Vector2D(x: 1.0, y: 2.0)
    let vectorToAdd = Vector2D(x: 3.0, y: 4.0)
    original += vectorToAdd
    // original 現(xiàn)在為 (4.0, 6.0)

你可以將 @assignment 屬性和 @prefix@postfix 屬性起來(lái)組合,實(shí)現(xiàn)一個(gè)Vector2D的前置運(yùn)算符。

    @prefix @assignment func ++ (inout vector: Vector2D) -> Vector2D {
        vector += Vector2D(x: 1.0, y: 1.0)
        return vector
    }

這個(gè)前置使用了已經(jīng)定義好的高級(jí)加賦運(yùn)算,將自己加上一個(gè)值為 (1.0,1.0) 的對(duì)象然后賦給自己,然后再將自己返回。

    var toIncrement = Vector2D(x: 3.0, y: 4.0)
    let afterIncrement = ++toIncrement
    // toIncrement 現(xiàn)在是 (4.0, 5.0)
    // afterIncrement 現(xiàn)在也是 (4.0, 5.0)

注意:
默認(rèn)的賦值符(=)是不可重載的。只有組合賦值符可以重載。三目條件運(yùn)算符 a?b:c 也是不可重載。

比較運(yùn)算符

Swift無(wú)所知道自定義類型是否相等或不等,因?yàn)榈扔诨蛘卟坏扔谟赡愕拇a說(shuō)了算了。所以自定義的類和結(jié)構(gòu)要使用比較符==!=就需要重載。

定義相等運(yùn)算符函數(shù)跟定義其他中置運(yùn)算符雷同:

    @infix func == (left: Vector2D, right: Vector2D) -> Bool {
        return (left.x == right.x) && (left.y == right.y)
    }

    @infix func != (left: Vector2D, right: Vector2D) -> Bool {
        return !(left == right)
    }

上述代碼實(shí)現(xiàn)了相等運(yùn)算符==來(lái)判斷兩個(gè)Vector2D對(duì)象是否有相等的值,相等的概念就是它們有相同的x值和相同的y值,我們就用這個(gè)邏輯來(lái)實(shí)現(xiàn)。接著使用==的結(jié)果實(shí)現(xiàn)了不相等運(yùn)算符!=。

現(xiàn)在我們可以使用這兩個(gè)運(yùn)算符來(lái)判斷兩個(gè)Vector2D對(duì)象是否相等。

    let twoThree = Vector2D(x: 2.0, y: 3.0)
    let anotherTwoThree = Vector2D(x: 2.0, y: 3.0)
    if twoThree == anotherTwoThree {
        println("這兩個(gè)向量是相等的.")
    }
    // prints "這兩個(gè)向量是相等的."

自定義運(yùn)算符

標(biāo)準(zhǔn)的運(yùn)算符不夠玩,那你可以聲明一些個(gè)性的運(yùn)算符,但個(gè)性的運(yùn)算符只能使用這些字符 / = - + * % < > ! & | ^ . ~。

新的運(yùn)算符聲明需在全局域使用operator關(guān)鍵字聲明,可以聲明為前置,中置或后置的。

    operator prefix +++ {}

這段代碼定義了一個(gè)新的前置運(yùn)算符叫+++,此前Swift并不存在這個(gè)運(yùn)算符。此處為了演示,我們讓+++對(duì)Vector2D對(duì)象的操作定義為 雙自增 這樣一個(gè)獨(dú)有的操作,這個(gè)操作使用了之前定義的加賦運(yùn)算實(shí)現(xiàn)了自已加上自己然后返回的運(yùn)算。

    @prefix @assignment func +++ (inout vector: Vector2D) -> Vector2D {
        vector += vector
        return vector
    }

Vector2D+++ 的實(shí)現(xiàn)和 ++ 的實(shí)現(xiàn)很接近, 唯一不同的是前者是加自己, 后者是加值為 (1.0, 1.0) 的向量.

    var toBeDoubled = Vector2D(x: 1.0, y: 4.0)
    let afterDoubling = +++toBeDoubled
    // toBeDoubled 現(xiàn)在是 (2.0, 8.0)
    // afterDoubling 現(xiàn)在也是 (2.0, 8.0)

自定義中置運(yùn)算符的優(yōu)先級(jí)和結(jié)合性

可以為自定義的中置運(yùn)算符指定優(yōu)先級(jí)和結(jié)合性??梢曰仡^看看優(yōu)先級(jí)和結(jié)合性解釋這兩個(gè)因素是如何影響多種中置運(yùn)算符混合的表達(dá)式的計(jì)算的。

結(jié)合性(associativity)的值可取的值有left,rightnone。左結(jié)合運(yùn)算符跟其他優(yōu)先級(jí)相同的左結(jié)合運(yùn)算符寫在一起時(shí),會(huì)跟左邊的操作數(shù)結(jié)合。同理,右結(jié)合運(yùn)算符會(huì)跟右邊的操作數(shù)結(jié)合。而非結(jié)合運(yùn)算符不能跟其他相同優(yōu)先級(jí)的運(yùn)算符寫在一起。

結(jié)合性(associativity)的值默認(rèn)為none,優(yōu)先級(jí)(precedence)默認(rèn)為100。

以下例子定義了一個(gè)新的中置符+-,是左結(jié)合的left,優(yōu)先級(jí)為140。

    operator infix +- { associativity left precedence 140 }
    func +- (left: Vector2D, right: Vector2D) -> Vector2D {
        return Vector2D(x: left.x + right.x, y: left.y - right.y)
    }
    let firstVector = Vector2D(x: 1.0, y: 2.0)
    let secondVector = Vector2D(x: 3.0, y: 4.0)
    let plusMinusVector = firstVector +- secondVector
    // plusMinusVector 此時(shí)的值為 (4.0, -2.0)

這個(gè)運(yùn)算符把兩個(gè)向量的x相加,把向量的y相減。因?yàn)樗麑?shí)際是屬于加減運(yùn)算,所以讓它保持了和加法一樣的結(jié)合性和優(yōu)先級(jí)(left140)。查閱完整的Swift默認(rèn)結(jié)合性和優(yōu)先級(jí)的設(shè)置,請(qǐng)移步表達(dá)式