首先要清楚常見的操做符有哪些?數組
對一元操做符來講包括'!'、'++'、'--',咱們經常使用的是非操做和自增操做。bash
咱們更熟悉二元操做符,好比a + b
在這個場景下'+'就是二元操做符,常見的二元操做符就是加減乘除等算術符號。ide
在Kotlin中還增長了其餘二元操做符,好比:in/!in(範圍操做符)。函數
另外還有一些其餘的操做符,好比索引訪問操做符a[i]、調用操做符a()。測試
你是否想過相似println("s" + 1)
這樣的代碼爲什麼會編譯經過,一個String類型和一個Int類型是如何相加的?爲何String類型能夠像數組同樣能夠經過下標訪問字符sss[1]
?ui
沒錯,不管'+' 仍是取索引都是一種操做符,Kotlin支持操做符的重載,也就是能夠將不一樣類型的對象進行算術運算或其它運算。this
咱們看看Kotling中String的源碼。spa
public class String : Comparable<String>, CharSequence {
companion object {}
//+操做符重載
public operator fun plus(other: Any?): String
//索引訪問操做符重載
public override fun get(index: Int): Char
...
}
複製代碼
操做符重載方法需聲明operator
關鍵字,plus方法對應'+'操做符,參數聲明爲Any?,可見正式由於String重載了'+'操做符,且參數爲Any?,因此在代碼中能夠用一個String類型的對象"+" 任意一個對象。code
接下來看一下操做符對應的重載方法名。對象
一元操做符 | 對應方法 |
---|---|
+a | a.unaryPlus() |
-a | a.unaryMinus() |
!a | a.not() |
a++/++a | a.inc() |
a--/--a | a.dec() |
二元操做符 | 對應方法 |
---|---|
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..b | a.rangeTo(b) |
a in b | b.contains(a) |
a !in b | !b.contains(a) |
a > b | a.compareTo(b) > 0 |
回到上面的例子,若是咱們稍微調整一下代碼 println(1+"s")
這樣就會編譯報錯,能夠想見Int類並不支持plus且參數爲String的重載。 咱們看一下Int類關於plus的重載函數。
# Int
/** Adds the other value to this value. */
public operator fun plus(other: Byte): Int
/** Adds the other value to this value. */
public operator fun plus(other: Short): Int
/** Adds the other value to this value. */
public operator fun plus(other: Int): Int
/** Adds the other value to this value. */
public operator fun plus(other: Long): Long
/** Adds the other value to this value. */
public operator fun plus(other: Float): Float
/** Adds the other value to this value. */
public operator fun plus(other: Double): Double
複製代碼
經過重載函數的聲明能夠確認Int類型只能與一個數字相 '+'。
接下來咱們舉幾個例子加深理解。
class Number constructor(var value: Int)
// 重載一元操做符+,使其對Number中實際數據取絕對值
operator fun Number.unaryPlus(): Number {
this.value = Math.abs(value)
return this
}
// 非運算取相反數
operator fun Number.not(): Number {
this.value = -value
return this
}
// 重載Number類的加法運算符 但並不作真正的加法
operator fun Number.plus(value: Int): Number {
return Number(this.value)
}
// 重載Number類的加法運算符 支持Number類型
operator fun Number.plus(value: Number): Number {
return Number(this.value)
}
// 重載Number類的索引運算 返回某個位上的數字
operator fun Number.get(index: Int): Int {
return this.value / Math.pow(10.toDouble(), index.toDouble()).toInt() % 10
}
複製代碼
測試函數
@JvmStatic
fun main(args: Array<String>) {
val number1 = Number(-3)
val number2 = Number(2)
println("Number value = ${number1.value}")
println("一元加法運算 value = ${(+number1).value}")
println("二元加法運算 value = ${(number1 + number2).value}")
val number3 = Number(876543210)
println("索引 number3 = ${number3[6]}")
}
//輸出
Number value = -3
一元加法運算 value = 3
二元加法運算 value = 3
索引 number3 = 6
複製代碼
上面的例子都比較好理解,操做符也是咱們常見的,試想一下Kotlin是否支持自定義的操做符呢?回答是確定的,它是Kotlin語言的一大特性。
來看一個栗子:
//定義String1類
class String1(var str: String)
//聲明中綴調用符"love"
infix fun String1.love(other: String1): String {
// return this.str + "love" + other.str//理想狀況
return if(other.str == "you") "gun" else "meizizi" //實際狀況
}
複製代碼
使用infix
關鍵字聲明中綴函數,中綴符爲'love',根據傳入參數判斷返回值,只要不是'you',都是美滋滋。若是是'you',心拔涼拔涼的。另需注意中綴函數也是擴展函數的一種,需在頂層包內聲明。
來測試一下看看效果。
@JvmStatic
fun main(args: Array<String>) {
val I = String1("i")
val YOU = String1("you")
//兩個String1類型之間支持中綴符'love'
print(I love YOU)
}
//輸出 gun
複製代碼