Kotlin操作符重載

操作符重載

一元操作符

表達(dá)式 對應(yīng)函數(shù)
+a a.unaryPlus()
-a a.unaryMinus()
!a a.not()
++a, a++ a.inc()
--a, a-- a.dec()

示例:

data class Point(val x: Int, val y: Int)
operator fun Point.unaryMinus() = Point(-x, -y)
operator fun Point.inc() = Point(x + 1, y + 1)
var p = Point(10, 20)
println(-p) // Point(x=10, y=-20)
println(++p) // Point(x=11, y=21)

二元操作符

表達(dá)式 對應(yīng)函數(shù)
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)

示例:

data class Point(val x: Int, val y: Int) {
    operator fun plus(other: Point): Point {
        return Point(x + other.x, y + other.y)
    }
}
val p1 = Point(10, 20)
val p2 = Point(30, 40)
println(p1 + p2) // Point(x=40, y=60)

沒有用于位運算的特殊運算符

  • shl — 帶符號左移
  • shr — 帶符號右移
  • ushr — 無符號右移
  • and — 按位與
  • or — 按位或
  • xor — 按位異或
  • inv — 按位取反

示例:

// kotlin
val num = 1 shl 4
println(num) // 16
==>
// java
int num = 1 << 4

in操作符

表達(dá)式 對應(yīng)函數(shù)
a in b b.contains(a)
a !in b !b.contains(a)

示例:

data class Rectangle(val upperLeft: Point, val lowerRight: Point)
operator fun Rectangle.contains(p: Point): Boolean {
    return p.x in upperLeft.x until lowerRight.x &&
        p.y in upperLeft.y until lowerRight.y
}
val rect = Rectangle(Point(10, 20), Point(50, 50))
println(Point(20, 30) in rect) // true

下標(biāo)訪問操作符(通過下標(biāo)來訪問元素:getset)

表達(dá)式 對應(yīng)函數(shù)
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)

示例:

// 一維
operator fun Point.get(index: Int): Int {
    return when(index) {
        0 -> x
        1 -> y
        else -> throw IndexOutOfBoundsException("Invalid coordinate $index")
    }
}

val p = Point(10, 20)
println(p[1]) // 20

// 二維
data class MutablePoint(var x: Int, var y: Int)
operator fun MutablePoint.set(index: Int, value: Int) {
    when(index) {
        0 -> x = value
        1 -> y = value
        else -> 
            throw IndexOutOfBoundsException("Invalid coordinate $index")
    }
}
val p = MutablePoint(10, 20)
p[1] = 42
println(p) // MutablePoint(x=10, y=42)

調(diào)用操作符(invoke)

表達(dá)式 對應(yīng)函數(shù)
a() a.invoke()
a(i) a.invoke(i)
a(i, j) a.invoke(i, j)
a(i_i, …, i_n) a.invoke(i_1, …, i_n)

圓括號轉(zhuǎn)換為調(diào)用帶有適當(dāng)數(shù)量參數(shù)的 invoke

示例:

class Greeter(val greeting: String) {
    operator fun invoke(name: String) {
        println("$greeting, $name!")
    }
}

val bavarianGreeter = Greeter("Servus") 
bavarianGreeter("Dmitry") // Servus, Dmitry!
==>
val bavarianGreeter = Greeter("Servus")("Dmitry") // Servus, Dmitry!

可以通過重寫invoke實例工廠模式

object Any {
    operator fun invoke(name: String): String {
        return name
    }
    
    operator fun invoke(number: Int): Int {
        return number
    }
}
val string = Any("Hello World!");
val int = Any("1");
println("$string, $int") // Hello World! 1

復(fù)合賦值運算符

表達(dá)式 對應(yīng)函數(shù)
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) (棄用)

示例:

operator fun <T> MutableCollection<T>.plusAssign(element: T) {
    this.add(element)
}
val list = arrayListOf(1, 2)
list += 3
val newList = list + listOf(4, 5)
println(list) // [1, 2, 3]
println(newList) // [1, 2, 3, 4, 5]

比較運算符(equals)

表達(dá)式 對應(yīng)函數(shù)
a == b a?.equals(b) ?: (b === null)
a != b !(a?.equals(b)) ?: (b ===null)

(等式校驗 == 被轉(zhuǎn)換為equals函數(shù)的調(diào)用宜雀,以及null的校驗)

注意===!==(同一性檢查)不可重載制跟,因此不存在對他們的約定撩嚼。

這個 == 操作符有些特殊:它被翻譯成一個復(fù)雜的表達(dá)式被丧,用于篩選 null 值齿诞。 null == null 總是 true指蚜,對于非空的 x麻裳,x == null 總是 false 而不會調(diào)用 x.equals()口蝠。

示例:

class Point(val x: Int, val y: Int) {
    override fun equals(obj: Any?): Boolean {
        if (obj === this) return true
        if (obj !is Point) return false
        return obj.x == x && obj.y == y
    }
}
println(Point(10, 20) == Point(10, 20)) // true
println(Point(10, 20) != Point(5, 5)) // true
println(null == Point(1, 2)) // false
表達(dá)式 函數(shù)名
+a unaryPlus
-a unaryMinus
!a not
++a, a++ inc
—a, a-- dec

示例:

operator fun Point.unaryMinus(): Point {
    return Point(-x, -y)
}
val p = Point(10, 20)
println(-p) // Point(x=10, y=-20)

比較操作符(compareTo)

表達(dá)式 對應(yīng)函數(shù)
a > b a.compareTo(b) > 0
a < b a.compareTo(b) < 0
a >= b a.compareTo(b) >= 0
a <= b a.compareTo(b) <= 0

所有的比較都轉(zhuǎn)換為對 compareTo 的調(diào)用,這個函數(shù)需要返回 Int

示例:

class Person(val firstName: String, val lastName: String): Comparable<Person> {
    override fun compareTo(other: Person): Int {
        return compareValuesBy(this, other, Person::lastName, Person::firstName)
    }
}
val p1 = Person("Alice", "Smith")
val p2 = Person("Bob", "Johnson")
println(p1 < p2) // false

參考資料:

Kotlin in Action

Operator overloading

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末津坑,一起剝皮案震驚了整個濱河市妙蔗,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌疆瑰,老刑警劉巖眉反,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狞谱,死亡現(xiàn)場離奇詭異,居然都是意外死亡禁漓,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門孵睬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來播歼,“玉大人,你說我怎么就攤上這事掰读∶啬” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵蹈集,是天一觀的道長烁试。 經(jīng)常有香客問我,道長拢肆,這世上最難降的妖魔是什么减响? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮郭怪,結(jié)果婚禮上支示,老公的妹妹穿的比我還像新娘。我一直安慰自己鄙才,他們只是感情好颂鸿,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著攒庵,像睡著了一般嘴纺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上浓冒,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天栽渴,我揣著相機與錄音,去河邊找鬼裆蒸。 笑死熔萧,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的僚祷。 我是一名探鬼主播佛致,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼辙谜!你這毒婦竟也來了俺榆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤装哆,失蹤者是張志新(化名)和其女友劉穎罐脊,沒想到半個月后定嗓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡萍桌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年宵溅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片上炎。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡恃逻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出藕施,到底是詐尸還是另有隱情寇损,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布裳食,位于F島的核電站矛市,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏诲祸。R本人自食惡果不足惜浊吏,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望烦绳。 院中可真熱鬧卿捎,春花似錦、人聲如沸径密。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽享扔。三九已至底桂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惧眠,已是汗流浹背籽懦。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留氛魁,地道東北人暮顺。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像秀存,于是被迫代替她去往敵國和親捶码。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容