Operator overloading
Kotlin中的运算符重载:在我们自己定义的类中,可以为一组预定义的运算操作提供自己的实现。这些运算符有固定的符号表示(*或+),以及固定的函数名称。为了实现这一个运算符,我们以固定名称的方式提供了成员函数或者扩展函数。比如如下类型:二目运算中靠左元素的数据类型以及一目运算的参数类型。重载符号函数必须使用关键字operator标识。
未来,我们会更加规划运算符重载。
一元运算符
一元前缀运算符
表达式翻译成
+aa.unaryPlus()-aa.unaryMinus()!aa.not()
以+a为例,解释下编译器的处理过程
确定a的类型,以T举例查找T类中是否含有unaryPlus函数,该方法用operator,扩展函数或者成员函数都可以如果该函数缺失或者有歧义,则编译失败如果该函数存在,并返回类型R,则该表达式类型为R
注意:基本类型的这些运算符都进行了优化,不会增加调用的开销
举个栗子
data
class Point(
val x: Int,
val y: Int)
operator
fun Point.unaryMinus() = Point(-x, -y)
fun main(args: Array<String>) {
val point = Point(
10,
20)
println(-point)
}
Point数据类有一个扩展函数unaryMinus(),所以当我们执行-point实际调用point.unaryMinus(),所以输出结果:
Point(x=
-10, y=-20)
递增和递减
表达式翻译成
a++a.inc()a–a.dec()
以a++为例
确定a的类型,以T表示在T对象实例的成员函数和扩展函数中查找是否含有inc()函数。检查函数返回类型是否是T的子类。
计算过程
将a的值存储到临时变量a0将a.inc()的计算结果赋值给a将a0的值作为结果返回
二目运算
算术运算
表达式翻译成
a + ba.plus(b)a - ba.minus(b)a * ba.times(b)a / ba.div(b)a % ba.rem(b)(1.1中加入), a.mod(b) (1.0,1.1中已废弃)a..ba.rangeTo(b)
举个栗子a+b
fun main(args:
Array<
String>) {
val counter =
Counter(
1)
println(counter +
3)
}
data class Counter(var dayIndex: Int) {
operator fun plus(increment: Int): Counter {
return Counter(dayIndex + increment)
}
}
执行结果:
Counter(dayIndex=
4)
in 操作
表达式翻译成
a in bb.contains(a)a !in b!b.contains(a)
索引操作
表达式翻译成
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] = ba.set(i, b)a[i, j] = ba.set(i, j, b)a[i_1, …, i_n] = ba.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)
增强作业
表达式翻译成
a += ba.plusAssign(b)a -= ba.minusAssign(b)a *= ba.timesAssign(b)a /= ba.divAssign(b)a %= ba.modAssign(b)
举个栗子 a+=b
首先判断plusAssign是否存在
如果存在
如果plus()和plusAssign(),有歧义,报错确保plusAssign()返回Unit,否则报错如果不存在,变换为a=a+b
相等和不等操作
表达式翻译成
a == ba?.equals(b) ?: (b === null)a != b!(a?.equals(b) ?: (b === null))
比较操作
表达式翻译成
a > ba.compareTo(b) > 0a < ba.compareTo(b) < 0a >= ba.compareTo(b) >= 0a <= ba.compareTo(b) <= 0