扩展函数
扩展函数表示即使在不修改某个类的源码的情况下,仍然可以打开这个类,向该类添加新的函数。
定义扩展函数的语法结构:
fun ClassName.methodName(param1: Int, param2: Int): Int {
return 0
}
相比定义普通函数,定义扩展函数只需要在函数名前加上一个 ClassName.
的语法结构,就表示将该函数添加到指定的类当中了。
扩展专用文件的命名约定通常是扩展类型加 Ext 后缀。扩展函数也是可以定义在任何一个现有类当中的,并不一定非要创建新文件。最好将它定义成顶层方法,这样可以让扩展函数拥有全局的访问域。
// 扩展函数
fun String.lettersCount(): Int {
var count = 0
// 函数中自动拥有了 String 实例的上下文,this 就代表着字符串本身
for (char in this) {
if (char.isLetter()) {
count++
}
}
return count
}
// 统计某个字符串中的字母数量
val count = "ABC123xyz!@#".lettersCount()
// 扩展属性
val String.numVowels
get() = count { "aeiouy".contains(it) }
在 Java 字节码里,Kotlin 扩展是个静态方法,其扩展对象就是它的一个值参。编译器会替换函数调用。
运算符重载
Kotlin 允许我们将所有的运算符甚至其他的关键字进行重载,从而扩展这些运算符和关键字的用法。
运算符重载使用的是 operator
关键字,只要在指定的函数前面算加上 operator 关键字,就可以实现运算符重载的功能了。任何类都可以重载这些运算符,但是,要确保有实际意义才去做。
比如加号运算符对应的是 plus()
函数,以此为例,它的语法结构如下:
class Obj {
operator fun plus(obj: Obj): Obj {
// 处理相加的逻辑
}
}
关键字 operator 和函数名 plus 都是固定不变的,而接收的参数和函数返回值可以根据你的逻辑自行设定。
对于 obj1 + obj2
,它会在编译的时候被转换成 obj1.plus(obj2)
的调用方式。
Kotlin 允许我们对同一个运算符进行多重重载。
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) |