Kotlin(十四) 扩展函数和运算符重载

目录

扩展函数

语法结构

代码示例

运算符重载

语法结构

一元操作符

二元操作符

数值类型操作符

等于和不等于操作符

比较操作符

调用操作符


扩展函数

语法结构

对于扩张函数的语法结构其实很简单,你想在那个类中添加扩张函数,那么你就用该类的类名加上点就可以,一般语法结构如下:

Kotlin 复制代码
fun ClassName.methodName(): Int {
    return 0
}

代码示例

Kotlin 复制代码
fun String.lettersCount(): Int {
    var count = 0
    for (letterChar in this) {
        if (letterChar.isLetter()) count++
    }
    return count
}

我们只需要创建一个为String.kt的文件,对于文件名我们可以随便命名,但是最好还是创建哪个类的扩展函数就以哪个类为文件名,这样便于查找,也方便后续的合作开发。

我们将lettersCount()方法定义成了String类的扩展函数,那么函数中就自动拥有了String实例的上下文。因此lettersCount()函数就不再需要接收一个字符串参数了,而是直接遍历this即可,因为现在this就代表着字符串本身。

定义好了扩展函数之后,统计某个字符串中的字母数量只需要这样写即可:

Kotlin 复制代码
    val count = "dshdhakjdas2u121jksd23424h".lettersCount()
    println("含有$count 个字母")

除了String类之外,你还可以向任何类中添加扩展函数,Kotlin对此基本没有限制。

运算符重载

语法结构

Kotlin 复制代码
class Obj{
    operator fun plus(obj: Obj) : Obj{
        //处理逻辑
    }
}

运算符重载使用的是operator关键字,只要在指定函数的前面加上operator关键字,就可以实现运算符重载的功能了。

在上述语法结构中,关键字operator和函数名plus都是固定不变的,而接收的参数和函数返回值可以根据你的逻辑自行设定。那么上述代码就表示一个Obj对象可以与另一个Obj对象相加,最终返回一个新的Obj对象。对应的调用方式如下:

Kotlin 复制代码
val obj1 = Obj()
val obj2 = Obj()
val obj3 = obj1 + obj2

这种obj1 + obj2的语法看上去好像很神奇,但其实这就是Kotlin给我们提供的一种语法糖,它会在编译的时候被转换成obj1.plus(obj2)的调用方式。

了解了运算符重载的基本语法之后,下面我们开始实现一个更加有意义功能:让两个Money对象相加。

首先定义Money类的结构,这里我准备让Money的主构造函数接收一个value参数,用于表示钱的金额。创建Money.kt文件,然后定义plus运算符重载,代码如下所示:

Kotlin 复制代码
class Money(val value: Int) {

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

可以看到,这里使用了operator关键字来修饰plus()函数,这是必不可少的。在plus()函数中,我们将当前Money对象的value和参数传入的Money对象的value相加,然后将得到的和传给一个新的Money对象并将该对象返回。这样两个Money对象就可以相加了,就是这么简单。除了plus()函数,Kotlin还提供了很多,如下:

一元操作符

操作符 方法名
+a a.unaryPlus()
-a a.unaryMinus()
!a a.not()
a++ a.inc()

二元操作符

操作符 方法名
a + b a.plus(b)
a -- b a.minus(b)
a * b a.times(b)
a / b a.div(b)
a % b a.mod(b)
a..b a.rangeTo(b)
a in b b.contains(a)
a !in b !b.contains(a)
a += b a.plusAssign(b)
a -= b a.minusAssign(b)
a *= b a.timesAssign(b)
a /= b a.divAssign(b)
a %= b a.modAssign(b)

数值类型操作符

操作符 方法名
a[i] a.get(i)
a[i, j] a.get(i, j)
a[i_1, ..., i_n] a.get(i_1, ..., i_n)
a[i] = b a.set(i, b)
a[i, j] = b a.set(i, j, b)
a[i_1, ..., i_n] = b a.set(i_1, ..., i_n, b)

等于和不等于操作符

操作符 方法名
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() a.invoke()
a(i) a.invoke(i)
a(i, j) a.invoke(i, j)
a(i_1, ..., i_n) a.invoke(i_1, ..., i_n)
相关推荐
DKPT11 分钟前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习
XeonYu13 分钟前
Kotlin 协程之 Flow 的理解使用及源码解析
kotlin·flow·coroutine
一笑的小酒馆1 小时前
Android性能优化之截屏时黑屏卡顿问题
android
耶啵奶膘1 小时前
uni-app头像叠加显示
开发语言·javascript·uni-app
看海天一色听风起雨落1 小时前
Python学习之装饰器
开发语言·python·学习
Want5951 小时前
C/C++圣诞树①
c语言·开发语言·c++
老赵的博客2 小时前
c++ 杂记
开发语言·c++
jimmy.hua2 小时前
[C++刷怪笼]:set/map--优质且易操作的容器
开发语言·c++
w2sfot3 小时前
Passing Arguments as an Object in JavaScript
开发语言·javascript·ecmascript
郝学胜-神的一滴3 小时前
避免使用非const全局变量:C++中的最佳实践 (C++ Core Guidelines)
开发语言·c++·程序人生