Kotlin操作符符重載
Kotlin 允許我們爲自己的類型提供預定義的一組操作符的實現。這些操作符具有固定的符號表示
(如 +
或 *
)和固定的優先級。爲實現這樣的操作符,我們爲相應的類型(即二元操作符左側的類型和一元操作符的參數類型)提供了一個固定名字的成員函數
或擴展函數。
重載操作符的函數需要用 operator
修飾符標記。
約定
在這裏我們描述爲不同操作符規範操作符重載的約定。
一元操作
表達式
翻譯爲
+a
a.unaryPlus()
-a
a.unaryMinus()
!a
a.not()
這個表是說,當編譯器處理例如表達式 +a
時,它執行以下步驟:
- 確定
a
的類型,令其爲T
。 - 爲接收者
T
查找一個帶有operator
修飾符的無參函數unaryPlus()
,即成員函數或擴展函數。 - 如果函數不存在或不明確,則導致編譯錯誤。
- 如果函數存在且其返回類型爲
R
,那就表達式+a
具有類型R
。
注意 這些操作以及所有其他操作都針對基本類型做了優化,不會爲它們引入函數調用的開銷。
表達式
翻譯爲
a++
a.inc()
+ 見下文
a--
a.dec()
+ 見下文
inc()
和 dec()
函數必須返回一個值,它用於賦值給使用++
或 --
操作的變量。它們不應該改變在其上調用 inc()
或 dec()
的對象。
編譯器執行以下步驟來解析後綴形式的操作符,例如 a++
:
- 確定
a
的類型,令其爲T
。 - 查找一個適用於類型爲
T
的接收者的、帶有operator
修飾符的無參數函數inc()
。 - 檢查函數的返回類型是
T
的子類型。
計算表達式的步驟是:
- 把
a
的初始值存儲到臨時存儲a0
中, - 把
a.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 中被棄用。
表達式
翻譯爲
a in b
b.contains(a)
a !in b
!b.contains(a)
對於 in
和 !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.modAssign(b)
{:#assignments}
對於賦值操作,例如 a += b
,編譯器執行以下步驟:
- 如果右列的函數可用
- 如果相應的二元函數(即
plusAssign()
對應於plus()
)也可用,那麼報告錯誤(模糊)。 - 確保其返回類型是
Unit
,否則報告錯誤。 - 生成
a.plusAssign(b)
的代碼
- 如果相應的二元函數(即
- 否則試着生成
a = a + b
的代碼(這裏包含類型檢查:a + b
的類型必須是a
的子類型)。
注意:賦值在 Kotlin 中不是表達式。
{:#Equals}
表達式
翻譯爲
a == b
a?.equals(b) ?: (b === null)
a != b
!(a?.equals(b) ?: (b === null))
注意:===
和 !==
(同一性檢查)不可重載,因此不存在對他們的約定
這個 ==
操作符有些特殊:它被翻譯成一個複雜的表達式,用於篩選 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
值
命名函數的中綴調用
我們可以通過中綴函數的調用 來模擬自定義中綴操作符。