Kotlin操作符重載實(shí)例詳解
算數(shù)運(yùn)算操作符重載
在kotlin中我定義一個(gè)類(lèi)
data class Point(val x: Int, val y: Int)
然后實(shí)例化兩個(gè)對(duì)象
val p1 = Point(3,5) val p2 = Point(5,7)
想表示p1的元素x加上p2的元素x,p1的元素y,加上p2的元素y.然后輸出一個(gè)p3.
val p3 = Point(p1.x + p2.x, p2.y + p2.y)
以上這種寫(xiě)法沒(méi)有任何問(wèn)題。不過(guò)我們可以利用Kotlin擴(kuò)展函數(shù)簡(jiǎn)化上面的操作,我們給Point增加一個(gè)plus,并附加operator關(guān)鍵字。(增加operator的關(guān)鍵字是為了區(qū)分plus并不是一個(gè)普通的成員方法)
data class Point(val x: Int, val y: Int) {
operator fun plus(other: Point): Point {
return Point(x + other.x, y + other.y)
}
}接下來(lái)再來(lái)實(shí)現(xiàn)上面的需求.
val p3 = p1 + p2
這樣表達(dá)起來(lái)更簡(jiǎn)潔了。 另外我們可以把plus作為Point的擴(kuò)展方法
data class Point(val x: Int, val y: Int)
operator fun Point.plus(other: Point): Point {
return Point(x + other.x, y + other.y)
}這種場(chǎng)景適用于Point存在于一個(gè)三方庫(kù),我們并能修改其中的內(nèi)容. Kotlin中提供了以下操作符的重載. 只需要實(shí)現(xiàn)對(duì)應(yīng)的方法即可。

之前我們定一個(gè)了plus,參數(shù)是Point,實(shí)際上對(duì)于個(gè)操作符重載并不局限于同一種類(lèi)型,接下來(lái)我們來(lái)定一個(gè)times,允許你去擴(kuò)展Ponit.
data class Point(val x: Int, val y: Int)
operator fun Point.times(scale: Double): Point {
return Point((x * scale).toInt(), (y * scale).toInt())
}
fun main(args: Array<String>) {
val p = Point(10, 20)
println(p * 1.5)
}注意kotlin不支持交換性,例如我這里寫(xiě)成1.5 * p這里是不允許的。除非你去定一個(gè)
operator fun Double.times(p: Point): Point
返回類(lèi)型同樣也可以不是同一個(gè)類(lèi)型,例如, 定義一個(gè)對(duì)char類(lèi)型重載*操作符重復(fù)count后返回一個(gè)string.
operator fun Char.times(count: Int): String {
return toString().repeat(count)
}
fun main(args: Array<String>) {
println('a' * 3)
}復(fù)合運(yùn)算操作符重載
我們?cè)诰幊踢^(guò)程中通常會(huì)去把這種寫(xiě)法p = p + p1 寫(xiě)成 p += p1 這種簡(jiǎn)化寫(xiě)法,在kotlin中同樣也支持這種+=操作符自定義操作。這種自定義運(yùn)算操作符在什么場(chǎng)景下使用呢? 舉個(gè)例子,我們定義集合
val numbers = ArrayList<Int>() numbers += 42 println(numbers[0])
以上寫(xiě)法會(huì)感覺(jué)更加簡(jiǎn)潔。 我們?cè)诩现卸x操作符重載方法plusAssign(這里還有minusAssign, timesAssign等等)
operator fun <T> MutableCollection<T>.plusAssign(element: T) {
this.add(element)
}不過(guò)kotlin-stblib庫(kù)已經(jīng)幫你實(shí)現(xiàn)好了關(guān)于集合的類(lèi)似操作. 在集合中+,-會(huì)累加集合原始后返回一個(gè)新的集合,如果使用+=,-=, 集合是mutable,會(huì)在本集合直接修改內(nèi)容,如果集合是read-only,會(huì)返回一個(gè)拷貝后的修改集合。(這意味著如果集合是read-only,它的聲明必須要是var, 不然它不能接受新返回拷貝后的修改集合). 你可以使用單獨(dú)的元素或者集合(類(lèi)型必須一致)進(jìn)行復(fù)合運(yùn)算符操作和算數(shù)運(yùn)算符.
val list = arrayListOf(1, 2) list += 3 val newList = list + listOf(4, 5) println(list) result : [1, 2, 3] println(newList) result : [1, 2, 3, 4, 5]
一元運(yùn)算操作符重載
我們?cè)诰幊踢^(guò)程中使用類(lèi)似++a, a++, --a, a--同樣支持運(yùn)算符重載。僅僅需要重寫(xiě)下面的操作符函數(shù)即可

舉個(gè)例子
operator fun BigDecimal.inc() = this + BigDecimal.ONE
fun main(args: Array<String>) {
var bd = BigDecimal.ZERO
println(bd++)
println(++bd)
}這里注意到我只定一個(gè)inc(),同時(shí)也是支持bd++和++bd.
比較操作符重載
kotlin中還支持==, !=, >, <操作符重載. 對(duì)于==, !=我們重寫(xiě)equals方法. 這里還是拿Point來(lái)舉栗子
data class Point(val x: Int, val y: Int)
我們這里聲明成了data類(lèi),這個(gè)關(guān)鍵字加上了編譯器會(huì)自動(dòng)幫你實(shí)現(xiàn)equals方法,我們現(xiàn)在去掉,看看自己去寫(xiě)equals怎么寫(xiě)
class Point(val x: Int, val y: Int) {
override fun equals(obj: Any?): Boolean {
if (obj === this) return true //1
if (obj !is Point) return false
return obj.x == x && obj.y == y
}
}
fun main(args: Array<String>) {
println(Point(10, 20) == Point(10, 20))
println(Point(10, 20) != Point(5, 5)) //2
println(null == Point(1, 2))
}這里我們需要關(guān)注一個(gè)//1 obj === this,這個(gè)===操作符是比較兩個(gè)對(duì)象的引用是否一致,實(shí)際上和java中的==是一樣的。 之前我們提到的操作符重載都會(huì)加上一個(gè)operator關(guān)鍵字,這里為什么是override?因?yàn)樗貙?xiě)了Any.class的equals方法.

這里看下//2!= 其實(shí)就是equals結(jié)果的取反. 除了=和!=之外這里還有>和<, 通過(guò)重寫(xiě)compareTo可以實(shí)現(xiàn)
class Person(
val firstName: String, val lastName: String
) : Comparable<Person> {
override fun compareTo(other: Person): Int {
return compareValuesBy(this, other,
Person::lastName, Person::firstName)
}
}
fun main(args: Array<String>) {
val p1 = Person("Alice", "Smith")
val p2 = Person("Bob", "Johnson")
println(p1 < p2)
}這里的compareValuesBy順便說(shuō)說(shuō),它是kotlin-stblib提供的擴(kuò)展函數(shù)

集合和區(qū)域的約定
在kotlin中我們可以使用類(lèi)似于操作數(shù)組的方法操作集合,例如a[b]這種. 對(duì)于其它類(lèi),可以自定義操作符實(shí)現(xiàn)類(lèi)似的操作
operator fun Point.get(index: Int): Int {
return when(index) {
0 -> x
1 -> y
else ->
throw IndexOutOfBoundsException("Invalid coordinate $index")
}
}
fun main(args: Array<String>) {
val p = Point(10, 20)
println(p[1])
}我們對(duì)于賦值操作同樣也可以通過(guò)自定義operator
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")
}
}
fun main(args: Array<String>) {
val p = MutablePoint(10, 20)
p[1] = 42
println(p)
}另外一個(gè)知識(shí)點(diǎn)是自定義in操作符

in對(duì)于的contains函數(shù),判斷一個(gè)元素是否屬于一個(gè)范圍里.
data class Point(val x: Int, val y: Int)
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
}
fun main(args: Array<String>) {
val rect = Rectangle(Point(10, 20), Point(50, 50))
println(Point(20, 30) in rect)
println(Point(5, 5) in rect)
}迭代運(yùn)算符重載
我們平時(shí)使用的
for (x in list) { ... }將被轉(zhuǎn)換為 list.iterator() 的調(diào)用,然后重復(fù)調(diào)用 hasNext 和 next 方法,就像在 Java 中一樣。 請(qǐng)注意,在 Kotlin 中,它也是一種約定,這意味著可以將迭代器方法定義為擴(kuò)展。這就解釋了為什么可以迭代常規(guī) Java 字符串:kotlin-stblib 在 Char-Sequence(String 的超類(lèi))上定義了一個(gè)擴(kuò)展函數(shù)迭代器:
operator fun CharSequence.iterator(): CharIterator
>>> for (c in "abc") {}其它類(lèi)型也可以通過(guò)自定義iterator實(shí)現(xiàn)自己類(lèi)特定的操作。
import java.util.Date
import java.time.LocalDate
operator fun ClosedRange<LocalDate>.iterator(): Iterator<LocalDate> =
object : Iterator<LocalDate> {
var current = start
override fun hasNext() =
current <= endInclusive
override fun next() = current.apply {
current = plusDays(1)
}
}
fun main(args: Array<String>) {
val newYear = LocalDate.ofYearDay(2017, 1)
val daysOff = newYear.minusDays(1)..newYear
for (dayOff in daysOff) { println(dayOff) }
}解構(gòu)聲明
這個(gè)操作可以分解一個(gè)對(duì)象中成員,例如
>>> val p = Point(10, 20) >>> val (x, y) = p >>> println(x) 10 >>> println(y) 20
解構(gòu)聲明看起來(lái)有點(diǎn)像變量聲明,不過(guò)它組合了多個(gè)變量值。實(shí)際上它在kotlin中也屬于自定義操作符.去解構(gòu)多個(gè)變量需要定義componentN,N是變量的位置.

class Point(val x: Int, val y: Int) {
operator fun component1() = x
operator fun component2() = y
}對(duì)于data類(lèi),解構(gòu)已經(jīng)幫你聲明好了 另外解構(gòu)聲明還可以用在循環(huán)中
fun printEntries(map: Map<String, String>) {
for ((key, value) in map) {
println("$key -> $value")
}
}
fun main(args: Array<String>) {
val map = mapOf("Oracle" to "Java", "JetBrains" to "Kotlin")
printEntries(map)
}Map中包含了擴(kuò)展方法component1,component2返回key和value. 實(shí)際上你可以將上面的循環(huán)部分翻譯成
for (entry in map.entries) {
val key = entry.component1()
val value = entry.component2()
// ...
}總結(jié)
到此這篇關(guān)于Kotlin操作符重載的文章就介紹到這了,更多相關(guān)Kotlin操作符重載內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)沉浸式狀態(tài)欄功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)沉浸式狀態(tài)欄功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10
Android開(kāi)發(fā)中記一個(gè)SwipeMenuListView側(cè)滑刪除錯(cuò)亂的Bug
這篇文章主要介紹了Android開(kāi)發(fā)中記一個(gè)SwipeMenuListView側(cè)滑刪除錯(cuò)亂的Bug的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
Android應(yīng)用圖標(biāo)在狀態(tài)欄上顯示實(shí)現(xiàn)原理
Android應(yīng)用圖標(biāo)在狀態(tài)欄上顯示,以及顯示不同的圖標(biāo),其實(shí)很研究完后,才發(fā)現(xiàn),很簡(jiǎn)單,具體實(shí)現(xiàn)如下,感興趣的朋友可以參考下哈2013-06-06
Android編程實(shí)現(xiàn)自定義進(jìn)度條顏色的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)自定義進(jìn)度條顏色的方法,涉及Android進(jìn)度條的樣式布局及功能實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11
Android實(shí)現(xiàn)app應(yīng)用多語(yǔ)言切換功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)app應(yīng)用多語(yǔ)言切換功能的相關(guān)資料,類(lèi)似于微信的語(yǔ)言切換,感興趣的小伙伴們可以參考一下2016-08-08
Android8.1 通過(guò)黑名單屏蔽系統(tǒng)短信和來(lái)電功能
最近小編接到一個(gè)新的需求,需要將8.1 設(shè)備的來(lái)電功能和短信功能都屏蔽掉,特殊產(chǎn)品就是特殊定制。接下來(lái)通過(guò)本文給大家介紹Android8.1 通過(guò)黑名單屏蔽系統(tǒng)短信和來(lái)電功能,需要的朋友參考下吧2019-05-05
Android——Android lint工具項(xiàng)目資源清理詳解
這篇文章主要介紹了Android——Android lint工具項(xiàng)目資源清理詳解的相關(guān)資料,需要的朋友可以參考下2016-11-11
Android實(shí)現(xiàn)pdf在線預(yù)覽或本地預(yù)覽的方法
下面小編就為大家分享一篇Android實(shí)現(xiàn)pdf在線預(yù)覽或本地預(yù)覽的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01

