kotlin更多語言結構——>操作符重載
Kotlin允許我們為自己的類型提供預定義的一組操作符的實現。這些操作符具有固定的符號表示(如 + 或 *) 和固定的優先級。為實現這樣的操作符,我們為相應的類型(即二元操作符左側的類型和一元操作符的參數類 型)提供了一個固定名字的成員函數或擴展函數。重載操作符的函數需要用 operator 修飾符標記。
另外,我們描述為不同操作符規范操作符重載的約定。
一元操作
一元前綴操作符
| 表達式 | 翻譯為 |
| +a | a.unaryPlus() |
| -a | a.unaryMinus() |
| !a | a.not() |
這個表是說,當編譯器處理例如表達式 +a 時,它執行以下步驟
— 確定 a 的類型,令其為 T;
— 為接收者 T 查找一個帶有 operator 修飾符的無參函數 unaryPlus(),即成員函數或擴展函數;
— 如果函數不存在或不明確,則導致編譯錯誤;
— 如果函數存在且其返回類型為 R,那就表達式 +a 具有類型 R;
注意 這些操作以及所有其他操作都針對基本類型做了優化,不會為它們引入函數調用的開銷。
以下是如何重載一元減運算符的示例
data class Point(val x: Int, val y: Int)
operator fun Point.unaryMinus() = Point(-x, -y)
val point = Point(10, 20)
fun main() {
println(-point) // 輸出“Point(x=-10, y=-20)”
}
遞增與遞減
| 表達式 | 翻譯為 |
| a++ | a.inc() |
| a-- | a.dec() |
inc() 和 dec() 函數必須返回一個值,它用于賦值給使用 ++ 或 -- 操作的變量。它們不應該改變在其上 調用 inc() 或 dec() 的對象
編譯器執行以下步驟來解析后綴形式的操作符,例如 a++
— 確定 a 的類型,令其為 T
— 查找一個適用于類型為 T 的接收者的、帶有 operator 修飾符的無參數函數 inc()
— 檢測函數的返回類型是 T 的子類型。
計算表達式的步驟是
— 把 a 的初始值存儲到臨時存儲 a0 中
— 把 a0.inc() 結果賦值給 a
— 把 a0 作為表達式的結果返回。
對于 a--,步驟是完全類似的。
對于前綴形式 ++a 和 --a 以相同方式解析,其步驟是:
— 把 a.inc() 結果賦值給 a
— 把 a 的新值作為表達式結果返回
二元操作
算術運算符
| 表達式 | 翻譯為 |
| a+b | a.plus(b) |
| a-b | a.minus(b) |
| a * b | a.times(b) |
| a / b | a.div(b) |
| a % b | a.rem(b) 、a.mod(b) (已棄用) |
| a..b | a.rangeTo(b) |
對于此表中的操作,編譯器只是解析成翻譯為列中的表達式。
請注意,自 Kotlin 1.1 起支持 rem 運算符。Kotlin 1.0 使用 mod 運算符,它在 Kotlin 1.1 中被棄用
示例:下面是一個從給定值起始的 Counter 類的示例,它可以使用重載的 + 運算符來增加計數
data class Counter(val dayIndex: Int) {
operator fun plus(increment: Int): Counter {
return Counter(dayIndex + increment) }
}
“In”操作符
| 表達式 | 翻譯為 |
| a in b | b.contains(a) |
| a !in b | !b.contains(a) |
對于 in 和 !in,過程是相同的,但是參數的順序是相反的
索引訪問操作符
| 表達式 | 翻譯為 |
| a[i] | a.get(i) |
| a[i,j] | a.get(i,j) |
| a[i_1,......,i_n] | a.get(i_1,......,i_n) |
| a[i] = b | a.set(i,b) |
| a[i,j] = b | a.set(i,j,b) |
| a[i_1 , ...... ,i_n] = b | a.set(i_1, ...... , i_n , b) |
方括號轉換為調用帶有適當數量參數的 get 和 set
調用操作符
| 表達式 | 翻譯為 |
| a() | a.invoke() |
| a(i) | a.invoke(i) |
| a(i , j) | a.invoke(i , j) |
| a(i_1 , ..... , i_n) | a.invoke(i_1,.......,i_n) |
圓括號轉換為調用帶有適當數量參數的 invoke
廣義賦值
| 表達式 | 翻譯為 |
| a += b | a.plusAssign(b) |
| a -= b | a.minusAssign(b) |
| a *= b | a.timesAssign(b) |
| a /= b | a.divAssign(b) |
| a %= b | a.remAssign(b) , a.modAssign(b)(已棄用) |
對于賦值操作,例如 a += b,編譯器執行以下步驟:
— 如果右列的函數可用
— 如果相應的二元函數(即 plusAssign() 對應于 plus())也可用,那么報告錯誤(模糊),
— 確保其返回類型是 Unit,否則報告錯誤,
— 生成 a.plusAssign(b) 的代碼;
— 否則試著生成 a = a + b 的代碼(這里包含類型檢測:a + b 的類型必須是 a 的子類型)。
注意:賦值在 Kotlin 中不是表達式
相等與不等操作符
| 表達式 | 翻譯為 |
| a == b | a?.equals(b) ?: (b === null) |
| a != b | !(a?.equals(b) ? : (b===null)) |
這些操作符只使用函數 equals(other: Any?): Boolean,可以覆蓋它來提供自定義的相等性檢測實現。 不會調用任何其他同名函數(如 equals(other: Foo))。
注意:=== 和 !==(同一性檢測)不可重載,因此不存在對他們的約定。
這個 == 操作符有些特殊:它被翻譯成一個復雜的表達式,用于篩選 null 值。null == null 總是 true,
對于非空的 x ,x == null 總是 false 而不會調用 x.equals()
比較操作符
| 表達式 | 翻譯為 |
| a > b | a.compareTo(b) > 0 |
| a < b | a.compareTo(b) < 0 |
| a >= b | a.compareTo(b) >= 0 |
| a <= b | a.compareTo(b) <= 0 |
所有的比較都轉換為對 compareTo 的調用,這個函數需要返回 Int 值
屬性委托操作符
provideDelegate 、getValue 以及 setValue 操作符函數已在委托屬性中描述
具名函數的中綴調用
我們可以通過中綴函數的調用 來模擬自定義中綴操作符
例:
infix fun Person.text(s:Student):Person = Person().plus(s)

浙公網安備 33010602011771號