Kotlin-操作符重载

来源:互联网 发布:网络回路检测 编辑:程序博客网 时间:2024/06/06 23:53

Kotlin允许我们为自己的类型提供预编译操作符集的实现。这些运算符具有固定的符号表示(像+或*)和固定的优先级.去实现操作符,我们为相应的类型提供固定名称的成员函数或者拓展函数,例如,二元运算的左边类型和一元运算的参数类型,可以允许被重载的函数都被operator关键字修饰。

此外,我们还描述了规范不同操作符操作符重载的约定

一元运算

一元运算的前置运算符

表达式 翻译后 +a a.unaryPlus() -a a.unaryMinus() !a a.not()

这个表格说明了编译器处理的情况,例如,表达式+a,它经过以下步骤:
- 确定a的类型,让它变为 T
- 查询接收器T中被operator 修饰的unaryPlus()函数,例如成员函数或拓展函数
- 如果没有这个函数或没有找到确定的函数,那就抛出编译异常
- 如果这个函数存在并且它的返回类型是R,表达式+a就是类型R

==注意,这些操作中,和其他操作一样,基本类型都有经过优化,这里就不再重复介绍它的应用==

这里给出一个如何重写一元运算操作符:

data class Point(val x: Int, val y: Int)operator fun Point.unaryMinus() = Point(-x, -y)val point = Point(10, 20)println(-point)  // prints "(-10, -20)"

自增和自减

表达式 翻译后 a++ a.inc()+看下面 a– a.dec()+看下面

inc()和dec()函数肯定有返回值,并且这个返回值会重新赋值给原来进行操作的变量,在执行inc和dec的时候,对象是不可以改变的。

编译器执行后缀操作符的时候会遵从以下规则,以a++为例:
- 确定a的类型,让它变为 T
- 查询被operator修饰的无参inc()函数,并应用到T中
- 检查这个函数的返回值类型是不是T的类型

表达式的计算效果如下:
- 保存a的初始值到临时参数a0中
- 把a.inc()的结果赋值给a
- 把a0作为表达式的结果返回

对于a–也是同样的道理

对于前缀++a和–a解决方式类似,效果如下:
- 把a.inc()的结果赋值给a
- 把a的新值作为表达式的结果返回

位运算

算术运算符

表达式 翻译后 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)

为执行这个表格中的操作,编译器会自动翻译成表格中翻译后的那些内容

==注意,reme操作是在版本1.1的时候才支持,在版本1.0的时候是使用mod操作符,这个操作符在版本1.1的时候就过期了==

示例

下面这个例子中就是根据提供的值通过重写+操作符来达到自增:

data class Counter(val dayIndex: Int) {    operator fun plus(increment: Int): Counter {        return Counter(dayIndex + increment)    }}

‘In’操作符

表达式 翻译后 a in b b.contains(a) a !in b !b.contains(a)

对于in和!in的程序是类似,只不过结果是相反

索引存取操作

表达式 翻译后 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)

方括号被翻译成为调用获取和设置对应参数的值

执行操作符

表达式 翻译后 a() a.invoke() a(i) a.invoke(i) a(i,j) a.invoke(i,j) a(i_1,…,i_n) a.invoke(i_1,…,i_n)

尖括号被翻译为以适当的参数调用invoke

赋值

表达式 | 翻译后
a += b | a.plusAssign(b)
a -= b | a.minusAssign(b)
a *= b | a.timesAssign(b)
a /= b | a.divAssign(b)
a %= b | a.modAssign(b)

对于赋值运算,拿a += b举例,编译器会进行以下操作:
- 表格右列的函数是否有效
- 相对应的二进制运算也要有效(如plushAssign()的plus),如果歧义就报错
- 确保返回类型是Unit,如果不是则报错
- 产生的代码是a.plusAssign(b)
- 否则,尝试去生成a = a + b(此代码中包含类型检查,a + b 的类型必须是a的类型)

==注意:赋值在Kotlin不是表达式==

等号和不等号运算符

表达式 | 翻译后
a == b | a?.equals(b) ?:(b === null)
a != b | !(a?.equals(b) ?: (b===null))

==注意:’===’ 和 ‘!== ‘(身份检查)不是重写操作,所以他们没有任何约定 ==

‘==’ 操作符是特例:它被翻译为用来检查是否非空的复杂表达式,null == null一直都是true,并且对于非空的 x总有x == null总为false的结果,并且它肯定不会执行x.equals().

比较运算符

表达式 | 翻译后
a > b | a.compareTo(b) > 0
a < b | a.compareTo(b) < 0
a >= b | a.compareTo(b) >= 0
a <= b | a.compareTo(b) <= 0

所有的比较运算都被翻译为调用compareTo,这些全部都返回Int类型.