前言
Kotlin 允许我们为自己的类型提供预定义的一组操作符的实现。这些操作符具有固定的符号表示 (如 + 或 *)和固定的优先级。为实现这样的操作符,我们为相应的类型(即二元操作符左侧的类型和一元操作符的参数类型)提供了一个固定名字的成员函数或扩展函数。 重载操作符的函数需要用 operator 修饰符标记。
操作符介绍
-
一元前缀操作符
表达式 +a -> 翻译为 a.unaryPlus()
表达式 -a -> 翻译为 a.unaryMinus()
表达式 !a -> 翻译为 a.not() -
执行的步骤
1 确定a的类型
2 为接收者 T 查找一个带有 operator 修饰符的无参函数 unaryPlus()
3 如果函数不存在或不明确,则导致编译错误;
4 如果函数存在且其返回类型为 R,那就表达式 +a 具有类型 R; -
使用实例
/**
* 表达式 +a -> 翻译为 a.unaryPlus()
* 表达式 -a -> 翻译为 a.unaryMinus()
* 表达式 !a -> 翻译为 a.not()
*/
data class Point(val x: Int, val y: Int)
// 负号一元前缀符
operator fun Point.unaryMinus() = Point(-x, -y)
// 正号一元前缀符
operator fun Point.unaryPlus() = Point(+x, +y)
// !一元前缀运算符
operator fun Point.not() = Point(x,y)
fun main() {
val p1 = Point(12, 24)
println(-p1)
println(!p1)
}
- 递增和递减
表达式 a++ -> 翻译为 a.inc()
表达式 a-- -> 翻译为 a.dec() - 执行的步骤
编译器执行以下步骤来解析后缀形式的操作符,例如 a++:
确定 a 的类型,令其为 T;
查找一个适用于类型为 T 的接收者的、带有 operator 修饰符的无参数函数 inc();
检测函数的返回类型是 T 的子类型。
计算表达式的步骤是:
把 a 的初始值存储到临时存储 a0 中;
把 a.inc() 结果赋值给 a;
把 a0 作为表达式的结果返回。
对于 a–,步骤是完全类似的。
对于前缀形式 ++a 和 --a 以相同方式解析,其步骤是:
把 a.inc() 结果赋值给 a;
把 a 的新值作为表达式结果返回。 - 使用实例
/***
* 递增运算符 ++point 会把新的结果返回
* 递增运算符 point++ 会把新的结果存储在一个变量中
*/
operator fun Point.inc() = Point(x + 1, y + 1)
/**
* 递减运算符 --point 会把新的结果返回
* 递增运算符 point++ 会把新的结果存储在一个变量中
*/
operator fun Point.dec() = Point(x - 1, y - 1)
fun main() {
var p1 = Point(12, 24)
p1 = ++p1
var p2 = p1++
println(p1)
println(p2)
}
- 二元操作符
表达式 | 翻译为 |
---|---|
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…b | a.rangTo(b) |
- 使用实例
/***
* 重载 + 这个运算符
*/
operator fun String.plus(s:String) = this+s
/***
* 重载 — 这个运算符
*/
operator fun String.minus(s:String) = this+ "减号运算符的重载"+s
fun main() {
var s = "栾小黑"
var ss = s+" hello world"
var sss = s-"helloworld"
println(ss)
println(sss)
}
对应的运算符对应的方法可以在官网上看到,运算符的重载最重要的是一个关键在 operator的使用