Kotlin 是一种适应你编程风格的语言。它允许你自定义运算符的实现,从而使代码更简洁、可读性更高。
在本主题中,你将学习如何为自定义数据类型定义自己的运算符实现。
运算符重载(Operator Overloading)
Kotlin 允许你为某些类型定义自定义运算符。这些运算符具有预定义的符号表示(如 +
或 +=
)以及优先级。要定义自定义运算符,需满足以下条件:
-
为对应类型提供一个具有特定名称的成员函数或扩展函数;
-
该类型将作为二元操作中的左操作数类型,或一元操作中的参数类型;
-
函数必须用
operator
关键字修饰。
示例 1:一元操作符重载(取反)
operator fun String.unaryMinus() = this.reversed()
fun main() {
val name = "Kotlin"
println(-name) // 输出:niltoK
}
解释:这里定义了字符串的取反操作 -
,行为是字符串反转。-name
实际会调用 name.unaryMinus()
。
示例 2:中缀表达式 + 运算符
infix operator fun String.times(n: Int) = this.repeat(n)
fun main() {
val s = "Kotlin"
println(s * 3) // 输出:KotlinKotlinKotlin
}
解释:这里定义了字符串 *
整数的操作,即重复字符串。你也可以使用 s times 3
写成中缀形式。
一元操作符(无参数)
表达式 | 实际转换为 |
---|---|
+a | a.unaryPlus() |
-a | a.unaryMinus() |
!a | a.not() |
a++ | a.inc() |
a-- | a.dec() |
operator fun Pair<Int, Int>.unaryMinus() = Pair(-first, -second)
operator fun Pair<Int, Int>.inc() = Pair(first + 1, second + 1)
fun main() {
var p = Pair(1, 2)
println(-p) // 输出:(-1, -2)
println(++p) // 输出:(2, 3)
}
二元操作符(两个参数)
表达式 | 实际转换为 |
---|---|
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.rangeTo(b) |
operator fun Pair<Int, Int>.plus(other: Pair<Int, Int>) =
Pair(first + other.first, second + other.second)
fun main() {
val p1 = Pair(1, 2)
val p2 = Pair(3, 4)
println(p1 + p2) // 输出:(4, 6)
}
in
运算符
表达式 | 实际转换为 |
---|---|
a in b | b.contains(a) |
a !in b | !b.contains(a) |
operator fun Pair<Int, Int>.contains(n: Int) = n in first..second
fun main() {
val p = Pair(1, 2)
println(1 in p) // 输出:true
}
下标运算符 []
表达式 | 实际转换为 |
---|---|
a[i] | a.get(i) |
a[i] = b | a.set(i, b) |
operator fun Pair<Int, Int>.get(n: Int) = when (n) {
0 -> first
1 -> second
else -> throw IndexOutOfBoundsException()
}
fun main() {
val p = Pair(1, 2)
println(p[0]) // 输出:1
println(p[1]) // 输出:2
}
函数调用运算符 ()
表达式 | 实际转换为 |
---|---|
a() | a.invoke() |
a(i) | a.invoke(i) |
operator fun Pair<Int, Int>.invoke(newLine: Boolean) {
print("($first, $second)")
if (newLine) println()
}
fun main() {
val p = Pair(1, 2)
p(true) // 输出:(1, 2)
}
复合赋值运算符 +=
、-=
等
表达式 | 实际转换为 |
---|---|
a += b | a.plusAssign(b) |
a -= b | a.minusAssign(b) |
operator fun StringBuilder.plusAssign(other: String) {
this.append(other)
}
fun main() {
val name = StringBuilder("Kotlin")
name += " is awesome"
println(name) // 输出:Kotlin is awesome
}
相等与不相等 ==
与 !=
表达式 | 实际转换为 |
---|---|
a == b | a?.equals(b) ?: (b === null) |
a != b | !(a?.equals(b) ?: (b === null)) |
class Point(val x: Int, val y: Int) {
override fun equals(other: Any?): Boolean {
return other is Point && other.x == x && other.y == y
}
}
fun main() {
val p1 = Point(1, 2)
val p2 = Point(1, 2)
println(p1 == p2) // 输出:true
}
比较运算符(需要实现 compareTo()
)
表达式 | 实际转换为 |
---|---|
a > b | a.compareTo(b) > 0 |
a < b | a.compareTo(b) < 0 |
class Point(val x: Int, val y: Int) : Comparable<Point> {
override fun compareTo(other: Point): Int {
return if (x == other.x) y.compareTo(other.y) else x.compareTo(other.x)
}
}
fun main() {
val p1 = Point(1, 2)
val p2 = Point(1, 2)
println(p1 < p2) // 输出:false
println(p1 <= p2) // 输出:true
}
总结
运算符重载是 Kotlin 提供的一个强大工具,可以让你的代码更具可读性与表现力。你只需满足函数命名、修饰符和签名的基本要求,就能为你的类型添加直观且易用的运算符。