Kotlin進階語法之操做符重載與中綴調用

操做符

首先要清楚常見的操做符有哪些?數組

對一元操做符來講包括'!'、'++'、'--',咱們經常使用的是非操做和自增操做。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
複製代碼
相關文章
相關標籤/搜索