运算符重载
Kotlin 允许您为预定义的一组类型操作符提供自定义实现。这些操作符具有预定义的符号表示(例如 +
或 *
)和优先级。 要实现一个操作符,可以为相应的类型提供一个 成员函数 或者 扩展函数 ,并使用特定的名称。
为了重载一个操作符,需要在相应的函数上标记 operator
修饰符:
当您重写操作符重载时,可以省略 operator
:
一元操作符
一元前缀操作符
表达式 | 转换为 |
---|---|
|
|
|
|
|
|
这个表格说明当编译器处理例如表达式 +a
时,它执行以下步骤:
确定
a
的类型,假设为T
。查找具有
operator
修饰符且没有参数的unaryPlus()
函数,用于接收者T
,即成员函数或扩展函数。如果函数不存在或不确定,则会编译错误。
如果函数存在且其返回类型为
R
,则表达式+a
的类型为R
。
以下是重载一元减号操作符的示例:
增量和减量操作符
表达式 | 转换为 |
---|---|
|
|
|
|
inc()
和 dec()
函数必须返回一个值,该值将赋给使用 ++
或 --
操作的变量。它们不应该改变调用 inc
或 dec
的对象。
编译器为解析 后缀 形式的操作符(例如 a++
)执行以下步骤:
确定
a
的类型,假设为T
。查找具有
operator
修饰符且没有参数的inc()
函数,适用于类型为T
的接收者。检查函数的返回类型是否是
T
的子类型。
计算表达式的效果如下:
将
a
的初始值存储到临时存储a0
中。将
a0.inc()
的结果赋给a
。将
a0
作为表达式的结果返回。
对于 a--
,步骤完全类似。
对于 前缀 形式 ++a
和 --a
,解析方式相同,效果是:
将
a.inc()
的结果赋给a
。将
a
的新值作为表达式的结果返回。
二元操作符
算术操作符
表达式 | 转换为 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
对于这个表中的操作,编译器会直接解析为 转换为 列中的表达式。
下面是一个示例 Counter
类,它从给定的值开始,并可以使用重载的 +
操作符进行增量:
in
操作符
表达式 | 转换为 |
---|---|
|
|
|
|
对于 in
和 !in
,解析过程相同,但参数的顺序是相反的。
索引访问操作符
表达式 | 转换为 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
方括号被转换为对应数量参数的 get
和 set
方法的调用。
调用操作符
表达式 | 转换为 |
---|---|
|
|
|
|
|
|
|
|
圆括号被转换为对应数量参数的 invoke
方法的调用。
复合赋值操作符
表达式 | 转换为 |
---|---|
|
|
|
|
|
|
|
|
|
|
对于赋值操作,例如 a += b
,编译器执行以下步骤:
如果右列的函数可用:
如果相应的二元函数(即
plus()
对应于plusAssign()
)也可用,并且a
是可变变量,并且plus
的返回类型是a
类型的子类型,则报告错误(模糊性)。确保其返回类型为
Unit
,否则报告错误。生成
a.plusAssign(b)
的代码。
否则,尝试生成
a = a + b
的代码(包括类型检查:a + b
的类型必须是a
的子类型)。
相等性和不等性操作符
表达式 | 转换为 |
---|---|
|
|
|
|
这些操作符只能使用 equals(other: Any?): Boolean
函数进行工作, 它可以被重写以提供自定义的相等性检查实现。任何其他具有相同名称的函数(如 equals(other: Foo)
)都不会被调用。
==
操作是特殊的:它被转换为一个复杂的表达式,用于检查 null
。 null == null
总是 true,对于非空的 x
, x == null
总是 false,并且不会调用 x.equals()
。
比较操作符
表达式 | 转换为 |
---|---|
|
|
|
|
|
|
|
|
所有比较操作都被转换为调用 compareTo
,该函数需要返回 Int
类型。
属性委托操作符
provideDelegate
、 getValue
和 setValue
操作符函数在 Delegated properties 中有详细描述。
命名函数的中缀调用
您可以通过使用 中缀函数调用 来模拟自定义的中缀操作。