1、簡(jiǎn)介
Swift中類(lèi)或結(jié)構(gòu)體可以對(duì)已有的運(yùn)算符進(jìn)行自定義實(shí)現(xiàn),賦予另外一種功能。可以成為運(yùn)算符函數(shù),即運(yùn)算符重載。
2、運(yùn)算符函數(shù)
2.1、雙目運(yùn)算符
下面將通過(guò)例子展示自定義結(jié)構(gòu)體如何實(shí)現(xiàn)加法運(yùn)算符(+)和減法運(yùn)算符(-),加法運(yùn)算符和減法運(yùn)算符是雙目運(yùn)算符,可以對(duì)兩個(gè)值進(jìn)行運(yùn)算,并且在兩個(gè)值之間。
例子中定義了一個(gè)Coordinate的結(jié)構(gòu)體,包含x和y兩個(gè)值,表示平面坐標(biāo)系上面的點(diǎn)。
struct Coordinate {
var x: Double = 0.0
var y: Double = 0.0
}
extension Coordinate {
static func +(lhs: Coordinate, rhs: Coordinate) -> Coordinate {
coordinate = Coordinate(x: lhs.x + rhs.x, y: lhs.y + rhs.y)
}
static func -(lhs: Coordinate, rhs: Coordinate) -> Coordinate {
coordinate = Coordinate(x: lhs.x - rhs.x, y: lhs.y - rhs.y)
}
}
上述兩個(gè)運(yùn)算符函數(shù)被定義為Coordinate的類(lèi)方法,運(yùn)算符函數(shù)名和重載的運(yùn)算符保持一致。加法運(yùn)算符(+)和減法運(yùn)算符(-)是雙目運(yùn)算符,因此接收兩個(gè)Coordinate類(lèi)型的參數(shù),返回一個(gè)Coordinate類(lèi)型的返回值。
上述兩個(gè)類(lèi)方法可以在任意兩個(gè)Coordinate實(shí)例之間作為中綴運(yùn)算符使用:
let point = Coordinate(x: 1.0, y: 1.0)
let anotherPoint = Coordinate(x: 2.0, y: 2.0)
let resultPoint1 = point + anotherPoint
let resultPoint2 = point - anotherPoint
print(resultPoint1)
print(resultPoint2)
這個(gè)例子中實(shí)現(xiàn)了(1.0,1.0)和(2.0,2.0)兩個(gè)點(diǎn)的相加和相減,得到兩個(gè)新的點(diǎn)(3.0,3.0)和(-1.0,-1.0)
Coordinate(x: 3.0, y: 3.0)
Coordinate(x: -1.0, y: -1.0)
2.2、前綴運(yùn)算符、后綴運(yùn)算符
2.1節(jié)的兩個(gè)運(yùn)算符函數(shù)實(shí)現(xiàn)了雙目運(yùn)算的自定義實(shí)現(xiàn)。類(lèi)和結(jié)構(gòu)體也可以實(shí)現(xiàn)單目運(yùn)算符,單目運(yùn)算符只運(yùn)算一個(gè)值。運(yùn)算符出現(xiàn)在值之前為前綴運(yùn)算符,出現(xiàn)在值之后為后綴運(yùn)算符。
實(shí)現(xiàn)單目運(yùn)算符需在在聲明運(yùn)算符函數(shù)時(shí)在func關(guān)鍵字之前添加prefix(前綴)(例如:-a)或postfix(后綴)(例如:b!)修飾符。
extension Coordinate {
static prefix func +(coordinate: Coordinate) -> Coordinate {
return Coordinate(x: +coordinate.x, y: +coordinate.y)
}
static prefix func -(coordinate: Coordinate) -> Coordinate {
return Coordinate(x: -coordinate.x, y: -coordinate.y)
}
}
上述的兩個(gè)運(yùn)算符函數(shù)為單目運(yùn)算運(yùn)算符函數(shù)。由于是前綴運(yùn)算符,需要在
func關(guān)鍵字之前加上prefix修飾符。
上述兩個(gè)運(yùn)算符函數(shù)只對(duì)Coordinate實(shí)例的x、y做簡(jiǎn)單的正負(fù)改變:
let point = Coordinate(x: 1.0, y: 1.0)
let anotherPoint = Coordinate(x: 2.0, y: 2.0)
print(-point)
print(+anotherPoint)
這個(gè)例子中對(duì)(1.0,1.0)和(2.0,2.0)兩個(gè)點(diǎn)進(jìn)行正負(fù)運(yùn)算,輸出結(jié)果為:
Coordinate(x: -1.0, y: -1.0)
Coordinate(x: 2.0, y: 2.0)
2.3、復(fù)合賦值運(yùn)算符
復(fù)合賦值運(yùn)算符是賦值運(yùn)算符(=)和其他運(yùn)算符進(jìn)行結(jié)合。例如加法運(yùn)算符(+)和賦值運(yùn)算符(=)相結(jié)合組成加法賦值運(yùn)算符(=+)。復(fù)合賦值運(yùn)算符函數(shù)需要將左值進(jìn)行inout關(guān)鍵修飾,因?yàn)樵诤瘮?shù)內(nèi)部要對(duì)左值進(jìn)行直接的修改。
extension Coordinate {
static func +=(lhs: inout Coordinate, rhs: Coordinate) {
lhs = Coordinate(x: lhs.x + rhs.x, y: lhs.y + rhs.y)
}
static func -=(lhs: inout Coordinate, rhs: Coordinate) {
lhs = Coordinate(x: lhs.x - rhs.y, y: lhs.y - rhs.y)
}
}
上述兩個(gè)運(yùn)算符函數(shù)實(shí)現(xiàn)了加法賦值運(yùn)算符和減法賦值運(yùn)算符的自定義。
var point = Coordinate(x: 1.0, y: 1.0)
let anotherPoint = Coordinate(x: 2.0, y: 2.0)
point += anotherPoint
print(point)
由于符合賦值運(yùn)算符函數(shù)的左值進(jìn)行了inout修飾,運(yùn)算的結(jié)果是對(duì)左值進(jìn)行直接的修改,輸入結(jié)果為:
Coordinate(x: 3.0, y: 3.0)
注意:不能對(duì)默認(rèn)的賦值運(yùn)算符(=)進(jìn)行重載,只有復(fù)合賦值運(yùn)算符可以重載。三目條件運(yùn)算符(a ? b : c)也不能進(jìn)行重載。
2.4、等價(jià)運(yùn)算符
自定義類(lèi)和結(jié)構(gòu)體沒(méi)有對(duì)等價(jià)運(yùn)算符進(jìn)行默認(rèn)的實(shí)現(xiàn)。等價(jià)運(yùn)算符一般被稱(chēng)為相等運(yùn)算符(==)和不等運(yùn)算符(!=)。
對(duì)于自定義的類(lèi)型,Swift無(wú)法進(jìn)行判等運(yùn)算,因?yàn)椤跋嗟取钡暮x取決于自定義類(lèi)型在代碼中扮演的角色。為了使自定義類(lèi)型能夠進(jìn)行等價(jià)運(yùn)算,我們可以對(duì)等價(jià)運(yùn)算符進(jìn)行自定義實(shí)現(xiàn)。
extension Coordinate {
static func ==(lhs: Coordinate, rhs: Coordinate) -> Bool {
if lhs.x == rhs.x && lhs.y == rhs.y {
return true
}
return false
}
static func !=(lhs: Coordinate, rhs: Coordinate) -> Bool {
if lhs.x != rhs.x || lhs.y != rhs.y {
return true
}
return false
}
}
上述的運(yùn)算符函數(shù)實(shí)現(xiàn)了“相等”運(yùn)算符,來(lái)判斷兩個(gè)Coordinate類(lèi)型是否相等,對(duì)于Coordinate類(lèi)型而言,相等表示兩個(gè)屬性“x”和“y”相等;“不等”運(yùn)算符表示只要Coordinate只要有一個(gè)屬性不相等,即可判斷為兩個(gè)Coordinate類(lèi)型不相等。
let point = Coordinate(x: 1.0, y: 1.0)
let anotherPoint = Coordinate(x: 2.0, y: 2.0)
print(point == anotherPoint)
print(point != anotherPoint)
由于point的兩個(gè)屬性x、y和anotherPoint的兩個(gè)屬性x、y值不相等,因此進(jìn)行相等(==)運(yùn)算的結(jié)果為false,進(jìn)行不等(!=)的運(yùn)算結(jié)果為true。
2.5、自定義運(yùn)算符
除了標(biāo)準(zhǔn)運(yùn)算符,Swift還可以聲明和實(shí)現(xiàn)自定義運(yùn)算符。
自定義運(yùn)算符需要在全局作用域通過(guò)關(guān)鍵字operator進(jìn)行定義,同時(shí)要指定prefix(前綴)、infix(中綴)或postfix(后綴)修飾符:
prefix operator +++
上面的代碼定義了一個(gè)名為+++的前綴運(yùn)算符。在Swift中+++并沒(méi)有實(shí)際的意義,我們可以通過(guò)Coordinate實(shí)例來(lái)定義它的意義。對(duì)于Coordinate類(lèi)型來(lái)講,可以將+++定義為雙自增前綴運(yùn)算符,實(shí)現(xiàn)Coordinate對(duì)自身的相加。
extension Coordinate {
static prefix func +++(coordinate: inout Coordinate) -> Coordinate {
coordinate += coordinate
return coordinate
}
}
上述中的運(yùn)算符函數(shù)通過(guò)自定義的加法賦值運(yùn)算符讓Coordinate實(shí)現(xiàn)自身的相加。
var point = Coordinate(x: 1.0, y: 6.0)
let anotherPoint = +++point
由于+++運(yùn)算符實(shí)現(xiàn)對(duì)自身相加,并輸出一個(gè)Coordinate實(shí)例,因此上述例子中point的值最終的結(jié)果為(2.0,12.0),anotherPoint的值為(2.0,12.0)。