Kotlin 基础07 - 扩展函数、运算符重载

扩展函数

扩展函数表示即使在不修改某个类的源码的情况下,仍然可以打开这个类,向该类添加新的函数。

定义扩展函数的语法结构:

1
2
3
fun ClassName.methodName(param1: Int, param2: Int): Int {
return 0
}

相比定义普通函数,定义扩展函数只需要在函数名前加上一个 ClassName. 的语法结构,就表示将该函数添加到指定的类当中了。

扩展专用文件的命名约定通常是扩展类型加 Ext 后缀。扩展函数也是可以定义在任何一个现有类当中的,并不一定非要创建新文件。最好将它定义成顶层方法,这样可以让扩展函数拥有全局的访问域。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 扩展函数
fun String.lettersCount(): Int {
var count = 0
// 函数中自动拥有了 String 实例的上下文,this 就代表着字符串本身
for (char in this) {
if (char.isLetter()) {
count++
}
}
return count
}
// 统计某个字符串中的字母数量
val count = "[email protected]#".lettersCount()


// 扩展属性
val String.numVowels
get() = count { "aeiouy".contains(it) }

在 Java 字节码里,Kotlin 扩展是个静态方法,其扩展对象就是它的一个值参。编译器会替换函数调用。

运算符重载

Kotlin 允许我们将所有的运算符甚至其他的关键字进行重载,从而扩展这些运算符和关键字的用法。

运算符重载使用的是 operator 关键字,只要在指定的函数前面算加上 operator 关键字,就可以实现运算符重载的功能了。任何类都可以重载这些运算符,但是,要确保有实际意义才去做。

比如加号运算符对应的是 plus() 函数,以此为例,它的语法结构如下:

1
2
3
4
5
6
class Obj {

operator fun plus(obj: Obj): Obj {
// 处理相加的逻辑
}
}

关键字 operator 和函数名 plus 都是固定不变的,而接收的参数和函数返回值可以根据你的逻辑自行设定

对于 obj1 + obj2 ,它会在编译的时候被转换成 obj1.plus(obj2) 的调用方式。

Kotlin 允许我们对同一个运算符进行多重重载。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Money(val value: Int) {

operator fun plus(money: Money): Money {
val sum = value + money.value
return Money(sum)
}

operator fun plus(newValue: Int): Money {
val sum = value + newValue
return Money(sum)
}

}

部分语法糖表达式和实际调用函数对照

语法糖表达式 实际调用函数
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++ a.inc()
a– a.dec()
+a a.unaryPlus()
-a a.unaryMinus()
!a a.not()
a == b a.equals(b)
a > b
a < b
a >= b a.compareTo(b)
a <= b
a..b a.rangeTo(b)
a[b] a.get(b)
a[b] = c a.set(b, c)
a in b b.contains(a)