Kotlin学习系列——运算符重载
Kotlin支持标准的算术运算表达式, 其中运算符被声明为相应类的成员。
Kotlin源代码中,我们可以自定义类型的运算符实现,即运算符的重载。这些运算符有固定的表示, 和固定的优先级。Kotlin为基本类型提供了固定名称的数值函数,比如二元运算符的左值和一元运算符的参数类型。
运算符的优先级
运算符重载
预定义的运算符的操作对象只能是基本数据类型,实际上,对于很多用户自定义类型,也需要有类似的运算操作。
运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据导致不同类型的行为。
运算符重载的实质是函数重载。在实现过程中,首先把指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参,然后根据实参的类型来确定需要调用达标函数,这个过程爱编译过程中完成。
一元运算符
算数运算符
表达式 | 转换 |
---|---|
+a | a.unaryPlus() |
-a | a.unaryMinus() |
!a | a.not() |
以表达式 +a为例,编译器的运行流程如下:
- 确定a的类型,假设为T
- 查找具有操作符修饰符的无参函数unaryPlus(),并且没有用于接收者T的参数,比如数值函数或扩展函数。
- 如果函数返回类型R,那么它必须是T的子类型。
注:这些操作符和其它的一样, 其操作的数据都被优化为基本类型并且不会产生多余的开销
自增自减
计算表达式的效果
- 把 a 的初始值存储在 a0 中
- 把 a.inc() 的结果作用在 a 上
- 把 a0 作为表达式的返回值
二元操作符
算术操作符
表达式 | 转换 |
---|---|
a + b | a.plus(b) |
a - b | a.minus(b) |
a * b | a.times(b) |
a / b | a.div(b) |
a % b | a.mod(b) |
a..b | a.rangeTo(b) |
编辑器只会处理“转换列中的表达式”
表达式 | 转换 |
---|---|
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,… ,o_n,b) |
方括号被转换为 get set 函数
标志 | 转换 |
---|---|
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为例分析编辑器运行
- 如果右列的函数可用
1. 确保相应的二进制函数(即plusAssign()的plus())也可用,否则发送错误报告
2. 确保其返回类型为Unit,否则发送错误报告
3.生成a.plusAssign(b)代码端
- 如果右列的函数不可用,尝试为a = a + b生成代码(包括类型检查:+ b的类型必须是a的子类型)。
表达式 | 转换 |
---|---|
a == b | a?.equals(b) ?: b.identityEquals(null) |
a != b | !(a?.equals(b) ?: b.identityEquals(null)) |
注意 === !== 是不允许重载的
==
如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等(若类型不同,高级转化为基础类型);
如果作用于引用类型的变量,则比较的是所指向的对象的地址
- equals
- equals方法不能作用于基本数据类型的变量
- 如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
3.诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。
- ===
1. 对于基本数据类型,如果类型不同,其结果就是不等。如果同类型相比,与“==”一致,直接比较其存储的 “值”是否相等;
2. 对于引用类型,与“==”一致,比较的是所指向的对象的地址
表达式 转换 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 值
位运算
对于位运算,Kotlin 并没有提供特殊的操作符, 只是提供了可以叫中缀形式的方法, 比如:
val x = (1 shl 2) and 0x000FF000
1
下面是全部的位运算操作符(只可以用在 Int 和 Long 类型):
* shl(bits) – 有符号左移 (相当于Java <<)
* shr(bits) – 有符号右移 (相当于Java >>)
* ushr(bits) – 无符号右移(相当于Java >>>)
* and(bits) – 按位与
* or(bits) – 按位或
* xor(bits) – 按位异或
* inv() – 按位取反
# 示例代码 #
# Data Class #
data class OperatorOverride(var name: String, var age: Int) {
// 重载 +a
operator fun unaryPlus() : OperatorOverride{
age = age.plus(100)
return this
}
// 重载 a++
operator fun inc() : OperatorOverride {
age += 10
return this
}
// 重载 a+b
operator fun plus(oo: OperatorOverride): OperatorOverride {
age += oo.age
return this
}
// 重载 equals
override fun equals(other: Any?): Boolean {
if (other is OperatorOverride) {
return this.age > other.age
}
return false
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Test #
fun main(args: Array<String>) {
var oo : OperatorOverride = OperatorOverride("zhang", 10)
println("----------------------------------")
println("原oo = ${oo}")
+oo
println("新oo = ${oo}")
println("----------------------------------")
println("----------------------------------")
println("原oo = ${oo}")
oo++
println("新oo = ${oo}")
println("----------------------------------")
println("----------------------------------")
val o : OperatorOverride = OperatorOverride("zhao", 43)
println("原oo = ${oo}")
println("新oo = ${oo + o}")
println("----------------------------------")
println("----------------------------------")
println(oo.equals(o)) // oo的age为120,o的age为43,故返回true
println("----------------------------------")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Log打印 #
----------------------------------
原oo = OperatorOverride(name=zhang, age=10)
新oo = OperatorOverride(name=zhang, age=110)
----------------------------------
----------------------------------
原oo = OperatorOverride(name=zhang, age=110)
新oo = OperatorOverride(name=zhang, age=120)
----------------------------------
----------------------------------
原oo = OperatorOverride(name=zhang, age=120)
新oo = OperatorOverride(name=zhang, age=163)
----------------------------------
----------------------------------
true
----------------------------------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
还没有评论,来说两句吧...