Kotlin 的操作符重载 机制允许开发者通过预定义函数名和 operator
修饰符,为自定义类型赋予与内置类型相似的操作符行为。以下是核心要点和示例:
一、操作符重载的实现方式
-
成员函数重载
在类内部声明特定名称的成员函数并标记
operator
:kotlindata class Point(val x: Int, val y: Int) { operator fun plus(other: Point) = Point(x + other.x, y + other.y) // + 操作符 :ml-citation{ref="2,4" data="citationList"} } val p1 = Point(1, 2) val p2 = Point(3, 4) println(p1 + p2) // 输出: Point(x=4, y=6)
-
扩展函数重载
为现有类添加操作符行为(无需修改原类):
kotlinoperator fun Point.minus(other: Point) = Point(x - other.x, y - other.y) // - 操作符 :ml-citation{ref="4,7" data="citationList"} println(p2 - p1) // 输出: Point(x=2, y=2)
二、常见操作符与对应函数
操作符类型 | 操作符示例 | 对应函数名 | 说明 |
---|---|---|---|
算术操作符 | + , - , * |
plus , minus , times |
优先级遵循数学规则(如 * 优先于 + )34 |
比较操作符 | == , > , < |
equals , compareTo |
== 调用 equals ,> 和 < 依赖 compareTo 68 |
索引操作符 | [] , []= |
get , set |
允许类似数组的访问和修改 34 |
调用操作符 | () |
invoke |
使对象可像函数一样调用 37 |
一元操作符 | +a , -a , ! |
unaryPlus , unaryMinus , not |
作用于单操作数 16 |
三、示例与应用场景
1. 自定义向量运算
kotlin
data class Vector(val x: Int, val y: Int) {
operator fun times(scalar: Int) = Vector(x * scalar, y * scalar) // * 操作符 :ml-citation{ref="2,4" data="citationList"}
}
val v = Vector(2, 3)
println(v * 5) // 输出: Vector(x=10, y=15)
2. 集合扩展操作
kotlin
operator fun List<Int>.get(indexes: IntRange): List<Int> { // 重载 [] 支持范围索引 :ml-citation{ref="3,7" data="citationList"}
return this.slice(indexes)
}
val list = listOf(1, 2, 3, 4, 5)
println(list[1..3]) // 输出: [2, 3, 4]
3. 自定义比较逻辑
kotlin
class Student(val score: Int) {
operator fun compareTo(other: Student) = score.compareTo(other.score) // > 和 < 操作符 :ml-citation{ref="6,8" data="citationList"}
}
val s1 = Student(85)
val s2 = Student(90)
println(s1 < s2) // 输出: true
四、注意事项
- 函数签名必须匹配
操作符函数的参数和返回类型需严格符合约定(如plus
需返回新对象)14。 - 避免滥用
过度重载可能降低代码可读性(如用+
表示非加法操作)26。 - 不可修改原对象
一元操作符(如inc()
)应返回新实例,而非修改原对象 68。
五、与 Java 的对比
特性 | Kotlin 操作符重载 | Java 实现方式 |
---|---|---|
语法简洁性 | 通过 operator 关键字直接支持 |
需手动实现特定方法(如 add 方法) |
扩展性 | 支持扩展函数重载 | 仅能通过类内部方法重载 |
操作符范围 | 覆盖更广(如 invoke ) |
有限支持(如 + 仅限字符串拼接) |
通过合理使用操作符重载,可显著提升代码表达力,但需遵循语义明确的原则