【kotlin】扩展函数和运算符重载
扩展函数扩展函数表示即使在不修改某个类的源码的情况下,仍然可以打开这个类,向该类添加新的函数如果想统计字符串中字母的数量,你可能会写出如下函数:object StringUtil {fun letterCount(string: String):Int{var count = 0for(str in string){if(str.isLetter()){count++}
扩展函数
扩展函数表示即使在不修改某个类的源码的情况下,仍然可以打开这个类,向该类添加新的函数
如果想统计字符串中字母的数量,你可能会写出如下函数:
object StringUtil {
fun letterCount(string: String):Int{
var count = 0
for(str in string){
if(str.isLetter()){
count++
}
}
return count
}
}
调用时
StringUtil.letterCount("123abc456def")
有了扩展函数,我们可以使用一种更加面向对象的思维来实现这个功能,比如说将 letterCount() 方法添加到 String 类中
先来学习扩展函数语法结构
fun ClassName.methodName(param1: Int, param2: Int): Int{
return 0
}
相对于定义一个普通的函数,定义扩展函数只需要在函数名前加上一个 ClassName. 的语法结构,就表示将该函数添加到指定类当中了
由于我们希望向 String 类中添加一个扩展函数,因此需要先创建一个 String.kt 文件。文件名虽无固定要求,但建议向哪个类添加扩展函数,就定义一个同名 Kotlin 文件。当然扩展函数也是可以定义在任何一个现有类当中,不一定非要创建新文件。通常来说,最好将它定义成顶层方法,这样可以让扩展函数拥有全局的访问域
String.kt 中编写如下代码:
fun String.letterCount():Int{
var count = 0
for(str in this){
if(str.isLetter()){
count++
}
}
return count
}
现在我们将 letterCount() 方法定义成了 String 类的扩展函数,那么函数就拥有了 String 实例的上下文,因此不需要再接收一个字符串参数了,直接遍历 this 即可,因为 this 就代表字符串本身
使用时
"123abc456def".letterCount()
运算符重载
+ - * /等运算符大家都用过,Kotlin 的运算符重载允许我们让任意两个对象进行相加,或者是进行更多其他的运算操作
运算符重载使用的是 operator 关键字,只要在指定函数前面加上 operator 关键字就可以实现运算符重载功能了。我们以加号运算符为例,来实现两个对象相加的功能
class Obj {
operator fun plus(obj: Obj): Obj {
//处理相加逻辑
}
}
上述语法结构中关键字 operater 和函数名 plus 都是固定不变的,接收参数和返回值根据你自己的逻辑设定。那么上述代码就表示一个 Obj 对象可以与另一个 Obj 对象相加,最终返回新的 Obj 对象。对应调用方式如下:
val obj1 = Obj()
val obj2 = Obj()
val obj3 = obj1 + obj2
最后两个对象相加看起来很神奇,它会在编译的时候被转换成 obj1.plus(obj2) 的调用方式
下面实现一个功能:让两个 Money 对象相加
首先定义好 Money 类的结构,让 Money 主构造函数接收一个 value 参数,用于表示钱的金额,然后使用运算符重载实现两个 Money 相加,创建 Money.kt 文件:
class Money(val value:Int){
operator fun plus(money: Money):Money{
val sum = value + money.value
return Money(sum)
}
}
测试
val money1 = Money(5)
val money2 = Money(10)
val money3 = money1 + money2
println(money3.value)
打印结果
如果 Money 对象能直接和数字相加就更好了,我们可以实现这个功能,因为 Kotlin 允许我们对同一个运算符进行多重重载:
class Money(val value:Int){
operator fun plus(money: Money):Money{
val sum = value + money.value
return Money(sum)
}
operator fun plus(int: Int):Money{
val sum = value + int
return Money(sum)
}
}
使用
val money1 = Money(5)
val money2 = money1 + 10
println(money2.value)
语法糖表达式和实际调用函数对照表
| 表达式 | 函数名 |
|---|---|
a + b |
plus |
a - b |
minus |
a * b |
times |
a / b |
div |
a % b |
rem,mod(弃用) |
| 表达式 | 函数名 |
|---|---|
+a |
unaryPlus |
-a |
unaryMinus |
!a |
not |
++a, a++ |
inc |
--a, a-- |
dec |
| 表达式 | 函数名 |
|---|---|
a == b |
a?.equals(b) ?: (b === null) |
a != b |
!(a?.equals(b) ?: (b === null)) |
a > b |
a.compareTo(b) > 0 |
a < b |
a.compareTo(b) < 0 |
a >= b |
a.compareTo(b) >= 0 |
a <= b |
a.compareTo(b) <= 0 |
| 表达式 | 函数名 |
|---|---|
a..b |
a.rangeTo(b) |
a[b] |
a.get(b) |
a[b] = c |
a.set(b,c) |
a in b |
b.contains(a) |
最后一个 a in b 表示判断 a 是否在 b 中,而 b.contains(a) 表示 b 是否包含 a
Kotlin 中 String 类就对 contains() 函数进行了重载,因此当我们判断 “hello” 中是否包含 “he” 可以这样写
if("hello".contains("he")){
}
借助重载的语法糖表达式,还可以这样写
if("he" in "hello"){
}
我们之前使用过一个随机生成字符串长度的函数
fun getRandomLenthString(str:String):String{
val n = (1..20).random()
val builder = StringBuilder()
repeat(n){
builder.append(str)
}
return builder.toString()
}
我们可以让一个字符串乘以一个数字来简化上面的方法,因此我们在 String.kt 中加入:
operator fun String.times(int:Int):String{
val builder = StringBuilder()
kotlin.repeat(int){
builder.append(this)
}
return builder.toString()
}
使用
Log.d("MainActivity","This is content "*3)
另外必须说明的是,Kotlin 类中已经提供了一个用于将字符串重复 n 遍的 repeat() 函数了,因此 times() 函数可以进一步精简为
operator fun String.times(int:Int) = repeat(int)
因此刚才的 getRandomLenthString()函数可以使用这种写法了:
fun getRandomLenthString(str:String) = str * (1..20).random()
更多推荐


所有评论(0)