
本篇文章為大家詳細的介紹Koltin特有的操作符重載。或許對於有編程經驗的朋友來說,操作符這個詞絕對不陌生,就算沒有任何編輯基礎的朋友,數學中的算數運算符也絕不陌生。例如(+、-、*、/、>、<、>=、<=)等。而算數運算符是編程語言中的一種操作符而已。就算你沒有任何基礎,也請你詳細的看完這篇文章,我相信你會很有收獲的。
目錄

一、約定
所謂預定:即指
Kotlin允許我們為自己的類型提供預定義的一組操作符的實現。這些操作符具有固定的符號表示(如+或*)和固定的優先級。為實現這樣的操作符,我們為相應的操作類型提供了一個固定名字的函數。這樣的技術,稱為約定
因為由類實現的接口集是固定的,而Kotlin不能為了實現其他接口而修改現有的類,因此一般通過擴展函數的機制來實現為現有的類增添新的約定方法,從而適應任何現有的Java類。
二、操作符與操作符重載
根據操作數據個數的不同,分為兩種操作類型:
- 一元操作:即指操作數只有一個的情況
- 二元操作:即指操作數存在二兩或多個的情況。特別說明:在存在多個操作數的情況下,會用復合運算或拆分為多個運算。
2.1、一元操作
一元操作:即指一個操作數的情況,
2.1.1、簡單的一元操作運算
這里分為三種情況有三種一元操作:
+表示為操作數實現一個正號的意思,其操作數為數值型-表示為操作數實現一個負號的意思,其操作數為數值型!表示取反的意思,其操作數為boolean類型
提供一個表格直觀的展示:
| 操作符 | 重載 |
|---|---|
| +a | a.unaryPlus() |
| -a | a.unaryMinus() |
| !a | a.not() |
例:
var a = 1
var b = -2
var c = true
var d = false
// 操作符實現
println("+a = ${+a}\t -a = ${-a}\t !c = ${!c}")
println("+b = ${+b}\t -b = ${-b}\t !d = ${!d}")
// 操作符重載實現
println("+a = ${a.unaryPlus()}\t -a = ${a.unaryMinus()}\t !c = ${c.not()}")
println("+b = ${b.unaryPlus()}\t -b = ${b.unaryMinus()}\t !d = ${d.not()}")
輸出結果為:
+a = 1 -a = -1 !c = false
+b = -2 -b = 2 !d = true
+a = 1 -a = -1 !c = false
+b = -2 -b = 2 !d = true
2.1.2、復雜的一元操作
復雜的一元操作符即指,對操作數進行自增、自減操作。和Java是一樣的
這里主要有4種情況:
- 后綴自增:表示為操作數進行自增操作,其操作數為數值型。例如:
a++- 后綴自減:表示為操作數進行自減操作,其操作數為數值型。例如:
a--- 前綴自增:表示為操作數進行自增操作,其操作數為數值型。例如:
++a- 前綴自減:表示為操作數進行自增操作,其操作數為數值型。例如:
--a
提供一個表格直觀的展示:
| 操作符 | 重載 | 表示 |
|---|---|---|
| a++ | a.inc() | a = a.also{ a.inc() } |
| a-- | a.dec() | a = a.also{ a.dec() } |
| ++a | a.inc() | a = a.inc().also{ a = it } |
| --a | a.dec() | a = a.dec().also{ a = it } |
解釋:操作符++的重載為inc(),操作符--的重載為dec()。但是前綴操作和后綴操作是有着明顯的區別的:
- 后綴操作是第一次調用的時候不執行自身。在第二次開始進行自增或自減操作。
- 前綴操作是第一次調用的時候就執行自增或自減操作
實例:
var a = 10
var b = 10
var c = 10
var d = 10
// 操作符實現
println("a++ = ${a++} \t b-- = ${b--} \t ++c = ${++c} \t --d = ${--d}")
// 操作符重載方式實現,或許你看不明白上表中代碼,不過這沒關系,你只要記住上面前綴與后綴操作的區別就行
a.also { a.inc() }
b.also { b.dec() }
c.inc().also { c = it }
d.dec().also { d = it }
println("a = $a \t b = $b \t c = $c \t d = $d")
輸出結果為:
a++ = 10 b-- = 10 ++c = 11 --d = 9
a = 10 b = 10 c = 11 d = 9
2.2 二元操作
二元操作:即指操作數存在二兩或多個的情況。
2.2.1、簡單的二元操作
簡單的二元操作有:
a + b,表示兩個操作數相加,值得注意的是若某一個操作數為String類型時。其返回值為String類型,當且僅當兩個操作數都為數值型時,其返回值才會數值型。a - b,表示兩個操作數相減,返回值為數值型a * b,表示兩個操作數相乘,返回值為數值型a / b,表示兩個操作數相除,返回值為數值型a % b,表示兩個操作數相除后的余數,官方稱之為模,即a模以b。返回值為Int型a .. b,表示范圍(區間),這里不詳細說明,在下面一點的區間操作符一起講解。
這里提供一個表格直觀的展示:
| 操作符 | 重載 |
|---|---|
| a + b | a.plus(b) |
| a - b | a.minus(b) |
| a * b | a.tiems(b) |
| a / b | a.div(b) |
| a % b | a.rem(b) 或 a.mod(b) |
| a .. b | a.rangTo(b) |
這里值得注意的是:a % b的重載為a.rem()或a.mod()。不過a.mod()是Koltin1.0版本的重載方法,現在已經棄用了,Koltin1.1以及以上版本使用a.rem()重載方法
例
// 簡單的二元操作
val a = 10
val b = 2
val c = "2"
val d = "Kotlin"
// 操作符實現
println("a + d = " + a + d)
println("c + d = " + c + d)
println("a + b = ${a + b} \t a - b = ${a - b} \t a * b = ${a * b} \t a / b = ${a / b} \t a % b = ${a % b}")
// 操作符重載實現
// println("a + d = ${a + d}") 錯誤:字符串模板限制只能為數值型
println("a + b = ${a.plus(b)} \t a - b = ${a.minus(b)} \t a * b = ${a.times(b)} \t a / b = ${a.div(b)} \t a % b = ${a.rem(b)}")
// println(a.plus(d)) 錯誤:因為第一個操作數`a`限制了其plus()方法的參數,
// println(d.plus(a)) 正確:因為plus()方法的參數為超(Any)類型
輸出結果為:
a + d = 10Kotlin
c + d = 2Kotlin
a + b = 12 a - b = 8 a * b = 20 a / b = 5 a % b = 0
a + b = 12 a - b = 8 a * b = 20 a / b = 5 a % b = 0
2.2.2、復合二元操作
復合的二元操作有:
a += b,表示第一個操作數的的值為第一個操作數加上第二個操作數,值得注意的是若某一個操作數為String類型時。其返回值為String類型,當且僅當兩個操作數都為數值型時,其返回值才會數值型。a -= b,表示第一個操作數的的值為第一個操作數減去第二個操作數,返回值為數值型a *= b,表示第一個操作數的的值為第一個操作數乘以第二個操作數,返回值為數值型a /= b,表示第一個操作數的的值為第一個操作數除以第二個操作數,返回值為數值型a %= b,表示第一個操作數的的值為第一個操作數模以第二個操作數 。返回值為Int型
這里提供一個表格直觀的展示:
| 操作符 | 表示 | 重載 |
|---|---|---|
| a += b | a = a + b | a = a.plus(b) |
| a -= b | a = a - b | a = a.minus(b) |
| a *= b | a = a * b | a = a.tiems(b) |
| a /= b | a = a / b | a = a.div(b) |
| a %= b | a = a % b | a = a.rem(b) |
例: 操作符實現
var b = 2
var a = 10
var c = "Kotlin"
// 主要演示字符串的+=
c += a 等價於 c = c.plus(a)
print("c = $c \t")
a += b 等價於 a = a.plus(b)
print("a = $a \t")
a = 10
a -= b 等價於 a = a.minus(b)
print("a = $a \t")
a = 10
a *= b 等價於 a = a.tiems(b)
print("a = $a \t")
a = 10
a /= b 等價於 a = a.div(b)
print("a = $a \t")
a = 10
a % b 等價於 a = a.rem(b)
print("a = $a \t")
輸出結果為:
c = Kotlin10 a = 12 a = 8 a = 20 a = 5 a = 0
或許你會說這里為什么沒有Kotlin的版本呢?你在看官方文檔或者其他人一些博客文章的時候可能有這樣a += b <=> a.plusAssign()的操作。但是我告訴你a.plusAssign()不是這樣用的,你可以看源碼知道primitives.kt文件中肯本就不存在plusAssign()這個方法。因為Koltin中賦值不是表達式。即 a += b <=> a = a + b在Kotlin中是a = a.plus(b)。不過數組與集合是同時存在plus()和plusAssign()這兩個函數的。
還有一點就是:如果我的第一個操作數定義為val(不可變)類型時,a += b這個表達式會編譯出錯。
上面說到了在源碼
primitievs.kt文件中不存在plusAssign()、minusAssign()、timesAssign()、divAssign()、remAssign()這些方法。那為什么官方文檔上會存在呢?這里這里不做詳解,但是我會在自定義重載操作符方法的時候給大家說明,請大家詳細的往下看,一些更高級的操作
2.3、位運算操作
位運算操作:即對一個數進行位移運算。關於這個操作符的重載函數,我在前面講解數據類型章節的時候已經講解過,這里就不多做累述了。沒有看過的朋友請參見Kotlin——初級篇(三):數據類型詳解
2.4、區間操作
區間操作符:即是符號..。值得注意的是這個操作符在Java中是不存在的,且兩個操作數都是整型
| 操作符 | 表示 | 重載 |
|---|---|---|
| a .. b | a 到 b 中間的值 | a.rangeTo(b) |
這個操作符一般用於for循環中,在條件判斷中偶爾也會用到。
例:
val a = 1
val b = 5
// 操作符實現
val s = 3 in a .. b // true,因為3在區間[1,5]之內
println("s = $s")
for (index in a .. b){
print("index = $index \t")
}
// 操作符重載方式實現
val t = 3 in a.rangeTo(b)
println("t = $t")
for (index in a.rangeTo(b)){
print("index = $index \t")
}
輸出結果為:
s = true
index = 1 index = 2 index = 3 index = 4 index = 5
t = true
index = 1 index = 2 index = 3 index = 4 index = 5
當然了,這些實例都是極其簡單的。我在Kotlin——初級篇(四):控制語句講解這篇文章也是講到過的。
總結
關於操作符重載,這里由於篇幅過長的原因,后面的比較操作符,以及in與is、以及自定義操作符等都會在下一章講解。敬請期待...
這篇文章,主要講解了Kotlin中常用的操作符以及重載方法。其中的第一部分只是介紹了其概念,在第二節在才開始講解了其用法及實例說明。重點在於二元操作中的復合運算一節,千萬不要被別人的博客和翻譯文檔所誤導。上面的實例都是我一個一個實驗過后才寫出來的。實踐出真理,不然我也不知道這個a += b等所
對應的a.plusAssign(b)等會這么坑。
參考
如果各位大佬看了之后感覺還闊以,就請各位大佬隨便star一下,您的關注是我最大的動力。
我的個人博客:Jetictors
我的github:Jetictors
我的掘金:Jetictors
