<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在kotlin中我定義一個類
data class Point(val x: Int, val y: Int)
然後範例化兩個物件
val p1 = Point(3,5) val p2 = Point(5,7)
想表示p1的元素x加上p2的元素x,p1的元素y,加上p2的元素y.然後輸出一個p3.
val p3 = Point(p1.x + p2.x, p2.y + p2.y)
以上這種寫法沒有任何問題。不過我們可以利用Kotlin擴充套件函數簡化上面的操作,我們給Point增加一個plus,並附加operator關鍵字。(增加operator的關鍵字是為了區分plus並不是一個普通的成員方法)
data class Point(val x: Int, val y: Int) { operator fun plus(other: Point): Point { return Point(x + other.x, y + other.y) } }
接下來再來實現上面的需求.
val p3 = p1 + p2
這樣表達起來更簡潔了。 另外我們可以把plus作為Point的擴充套件方法
data class Point(val x: Int, val y: Int) operator fun Point.plus(other: Point): Point { return Point(x + other.x, y + other.y) }
這種場景適用於Point存在於一個三方庫,我們並能修改其中的內容. Kotlin中提供了以下操作符的過載. 只需要實現對應的方法即可。
之前我們定一個了plus,引數是Point,實際上對於個操作符過載並不侷限於同一種型別,接下來我們來定一個times,允許你去擴充套件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不支援交換性,例如我這裡寫成1.5 * p這裡是不允許的。除非你去定一個
operator fun Double.times(p: Point): Point
返回型別同樣也可以不是同一個型別,例如, 定義一個對char型別過載*操作符重複count後返回一個string.
operator fun Char.times(count: Int): String { return toString().repeat(count) } fun main(args: Array<String>) { println('a' * 3) }
我們在程式設計過程中通常會去把這種寫法p = p + p1 寫成 p += p1 這種簡化寫法,在kotlin中同樣也支援這種+=操作符自定義操作。這種自定義運算操作符在什麼場景下使用呢? 舉個例子,我們定義集合
val numbers = ArrayList<Int>() numbers += 42 println(numbers[0])
以上寫法會感覺更加簡潔。 我們在集合中定義操作符過載方法plusAssign(這裡還有minusAssign, timesAssign等等)
operator fun <T> MutableCollection<T>.plusAssign(element: T) { this.add(element) }
不過kotlin-stblib庫已經幫你實現好了關於集合的類似操作. 在集合中+,-會累加集合原始後返回一個新的集合,如果使用+=,-=, 集合是mutable,會在本集合直接修改內容,如果集合是read-only,會返回一個拷貝後的修改集合。(這意味著如果集合是read-only,它的宣告必須要是var, 不然它不能接受新返回拷貝後的修改集合). 你可以使用單獨的元素或者集合(型別必須一致)進行復合運運算元操作和算數運運算元.
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]
我們在程式設計過程中使用類似++a, a++, --a, a--同樣支援運運算元過載。僅僅需要重寫下面的操作符函數即可
舉個例子
operator fun BigDecimal.inc() = this + BigDecimal.ONE fun main(args: Array<String>) { var bd = BigDecimal.ZERO println(bd++) println(++bd) }
這裡注意到我只定一個inc(),同時也是支援bd++和++bd.
kotlin中還支援==, !=, >, <操作符過載. 對於==, !=我們重寫equals方法. 這裡還是拿Point來舉栗子
data class Point(val x: Int, val y: Int)
我們這裡宣告成了data類,這個關鍵字加上了編譯器會自動幫你實現equals方法,我們現在去掉,看看自己去寫equals怎麼寫
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)) }
這裡我們需要關注一個//1 obj === this,這個===操作符是比較兩個物件的參照是否一致,實際上和java中的==是一樣的。 之前我們提到的操作符過載都會加上一個operator關鍵字,這裡為什麼是override?因為它重寫了Any.class的equals方法.
這裡看下//2!= 其實就是equals結果的取反. 除了=和!=之外這裡還有>和<, 通過重寫compareTo可以實現
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順便說說,它是kotlin-stblib提供的擴充套件函數
在kotlin中我們可以使用類似於運算元組的方法操作集合,例如a[b]這種. 對於其它類,可以自定義操作符實現類似的操作
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]) }
我們對於賦值操作同樣也可以通過自定義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) }
另外一個知識點是自定義in操作符
in對於的contains函數,判斷一個元素是否屬於一個範圍裡.
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) }
我們平時使用的
for (x in list) { ... }
將被轉換為 list.iterator() 的呼叫,然後重複呼叫 hasNext 和 next 方法,就像在 Java 中一樣。 請注意,在 Kotlin 中,它也是一種約定,這意味著可以將迭代器方法定義為擴充套件。這就解釋了為什麼可以迭代常規 Java 字串:kotlin-stblib 在 Char-Sequence(String 的超類)上定義了一個擴充套件函數迭代器:
operator fun CharSequence.iterator(): CharIterator >>> for (c in "abc") {}
其它型別也可以通過自定義iterator實現自己類特定的操作。
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) } }
這個操作可以分解一個物件中成員,例如
>>> val p = Point(10, 20) >>> val (x, y) = p >>> println(x) 10 >>> println(y) 20
解構宣告看起來有點像變數宣告,不過它組合了多個變數值。實際上它在kotlin中也屬於自定義操作符.去解構多個變數需要定義componentN,N是變數的位置.
class Point(val x: Int, val y: Int) { operator fun component1() = x operator fun component2() = y }
對於data類,解構已經幫你宣告好了 另外解構宣告還可以用在迴圈中
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中包含了擴充套件方法component1,component2返回key和value. 實際上你可以將上面的迴圈部分翻譯成
for (entry in map.entries) { val key = entry.component1() val value = entry.component2() // ... }
到此這篇關於Kotlin操作符過載的文章就介紹到這了,更多相關Kotlin操作符過載內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45