在本主题中,你将学习如何为自定义数据类型定义自己的运算符实现。
Kotlin 允许你为某些类型定义自定义运算符。这些运算符具有预定义的符号表示(如 +
或 +=
)以及优先级。要定义自定义运算符,需满足以下条件:
为对应类型提供一个具有特定名称的成员函数或扩展函数;
该类型将作为二元操作中的左操作数类型,或一元操作中的参数类型;
函数必须用 operator
关键字修饰。
operator fun String.unaryMinus() = this.reversed()
fun main() {
val name = "Kotlin"
println(-name) // 输出:niltoK
}
解释:这里定义了字符串的取反操作 -
,行为是字符串反转。-name
实际会调用 name.unaryMinus()
。
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 提供的一个强大工具,可以让你的代码更具可读性与表现力。你只需满足函数命名、修饰符和签名的基本要求,就能为你的类型添加直观且易用的运算符。