千家信息网

Kotlin操作符重载的方法

发表于:2025-02-01 作者:千家信息网编辑
千家信息网最后更新 2025年02月01日,这篇"Kotlin操作符重载的方法"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇"Ko
千家信息网最后更新 2025年02月01日Kotlin操作符重载的方法

这篇"Kotlin操作符重载的方法"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇"Kotlin操作符重载的方法"文章吧。

算数运算操作符重载

在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) {    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) {    println('a' * 3)}

复合运算操作符重载

我们在编程过程中通常会去把这种写法p = p + p1 写成 p += p1 这种简化写法,在kotlin中同样也支持这种+=操作符自定义操作。这种自定义运算操作符在什么场景下使用呢? 举个例子,我们定义集合

val numbers = ArrayList()numbers += 42println(numbers[0])

以上写法会感觉更加简洁。 我们在集合中定义操作符重载方法plusAssign(这里还有minusAssign, timesAssign等等)

operator fun  MutableCollection.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.ONEfun main(args: Array) {    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) {    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 {    override fun compareTo(other: Person): Int {        return compareValuesBy(this, other,            Person::lastName, Person::firstName)    }}fun main(args: Array) {    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) {    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) {    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) {    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.Dateimport java.time.LocalDateoperator fun ClosedRange.iterator(): Iterator =        object : Iterator {            var current = start            override fun hasNext() =                current <= endInclusive            override fun next() = current.apply {                current = plusDays(1)            }        }fun main(args: Array) {    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) {    for ((key, value) in map) {        println("$key -> $value")    }}fun main(args: Array) {    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操作符重载的方法"这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注行业资讯频道。

操作符 方法 运算 内容 元素 类型 函数 支持 关键 关键字 写法 实际 实际上 运算符 面的 迭代 变量 对象 知识 简洁 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 dz安装填写数据库怎么写 取多张表不重复数据库 淘宝如何开软件开发店铺 网络安全班会教案设计 我的世界pe饥饿服务器 玉溪软件开发培训学校 服务器put请求失败 电信怎么开通三爱服务器 扫一扫的软件开发 一个数据库可以两个网址吗 崇明区微型网络技术采购信息 服务器主机的温度高是什么意思 桓台县网络安全办 计算机网络安全专业难吗 上海凡事网络技术有限公司 网络安全对国家安全重要性 文献数据库分为哪几种 南京信息工程大学网络技术 广州财务软件开发教程 无线网络技术教程章节 电脑服务器数据库版本低 全球知名服务器搭建 菏泽党员教育软件开发公司 轨迹定位软件开发 给我的服务器取个名 现在都不学关系数据库了吗 设计 信息 网络安全方案 甲方软件开发会裁员吗 银行软件开发外包人员面试题 设定数据库的临时表空间
0