当前位置:网站首页>【Kotlin学习】运算符重载及其他约定——重载算术运算符、比较运算符、集合与区间的约定
【Kotlin学习】运算符重载及其他约定——重载算术运算符、比较运算符、集合与区间的约定
2022-07-03 08:59:00 【安卓老猴子】
重载算术运算符
重载二元运算符
定义一个plus运算符

注意!如何使用operator关键字来声明plus函数。用于重载运算符的所有函数都需要用该关键字标记,用来表示你打算把这个函数作为相应的约定的实现,并且不是碰巧地定义一个同名函数
在使用了operator修饰符声明了plus函数后,你就可以直接使用+号来求和
a + b =a.plus(b)
除了把这个运算符声明为一个成员函数外,也可以把它定义为一个扩展函数

这是给第三方库的类定义约定扩展函数的常用模式
可重载的二元算术运算符
自定义类型的运算符,基本上和标准数字类型的运算符有着同样的优先级
| 运算符 | 对应函数 |
|---|---|
| a*b | times |
| a/b | div |
| a%b | mod |
| a+b | plus |
| a-b | minus |
运算符函数与java
从java调用kotlin的运算符只需要像普通函数那样调用它们就行。当kotlin调用java的时候,对于与kotlin约定匹配的函数都可以使用运算符语法来调用。由于java没有定义任何用于标记运算符函数的语法,所以使用operator修饰符的要求对它不适用,唯一的约束是,参数需要匹配名称和数量。若java定义了一个满足需求的函数,但起了一个不同的名称,可以通过定义一个扩展函数来修正这个函数名
当你在定义一个运算符时,不要求两个运算数是相同类型

注意!kotlin不会自动支持交换性(交换运算符的左右两边)。如果希望支持,你需要为它定义一个单独的运算符

运算符函数也可以不同于任一运算数类型

这个运算符接收一个Char作为左值,Int作为右值,然后返回一个String类型,这样的运算数和结果类型组合是允许的
和普通的函数一样,可以重载operator函数:可以定义多个同名的,但参数类型不同的方法
没有用于位运算的特殊运算符
kotlin没有为标准数字类型定义任何位运算符,因此也不允许你为自定义类型定义它们。相反,它支持使用中缀调用语法的常规函数,可以为自定义类型定义相似的函数
| 函数名 | 含义 |
|---|---|
| shl | 带符号左移 |
| shr | 带符号右移 |
| ushr | 无符号右移 |
| and | 按位与 |
| or | 按位或 |
| xor | 按位异或 |
| inv | 按位取反 |
重载复合赋值运算符
kotlin也支持+=这些复合赋值运算符(下图的+=需要自己定义)

在一些情况下,定义+=运算可以修改使用它的变量所引用的对象,但不会重新分配引用。比如将一个元素添加到可变集合

如果你定义了一个返回值为Unit,名为plusAssign的函数,kotlin将会在用到+=运算符的地方调用它。其他二元算术运算符也有命名相似的对应函数:如minusAssign、timesAssign
当代码中使用到+=的时候,理论上plus和plusAssign都可能被调用。在这种情况下,两个函数都有定义且适用,编译器会报错。一种解决办法是,替换运算符的使用为普通函数调用。另一个办法是用val替代var,这样plusAssign不再适用。一般来说最好在设计新类时保持可变性一致,尽量不要同时给一个类添加plus和plusAssign运算。如果一个类是不可变的,那么就应该只提供返回一个新值的运算。如果一个类是可变的,那么只需要提供plusAssign运算即可
+和-运算符总是返回一个新的集合。+=和-=运算符用于可变集合时,始终就地修改它们。而它们用于只读集合时,hi返回一个修改过的副本(这意味着只有当引用只读集合的变量被声明为var时才能使用+=和-=),作为它们的运算数,可以使用单个元素,也可以使用元素类型一致的其他集合
重载一元运算符
方式和前面的一样,此处不详写
| 运算符 | 对应函数 |
|---|---|
| +a | unaryPlus |
| -a | unaryMinus |
| !a | not |
| ++a/a++ | inc |
| –a/a– | dec |
当你定义inc和dec函数来重载自增和自减运算符时,编译器自动支持与普通数字类型的前缀和后缀自增运算符相同的语义,所以不需要分开前缀和后缀定义
重载比较运算符
等号运算符:“equals”
在kotlin中使用==运算符,它将会被转换成equals方法的调用,!=也一样,只是结果相反。与其他运算符不同的是。它们两个可以用于可空运算数,因为这些运算符事实上会检查运算数是否为null
a==b -> a?.equals(b)?:(b==null)
对于上方的Point类,因为已经被标记为数据类,equals的实现会由编译器完成
手动实现

首先检查是否和this是同一个对象,然后检查参数类型,之后再访问x,y属性来判断。这里使用了恒等运算符来检查参数与调用equals的对象是否相同。恒等运算符与java中的==运算符是完全相同的:检查两个参数是否是同一个对象的引用,如果是基本数据类型,则检查它们是否是相同的值。注意!===不能被重载。
equals之所以被标记为override,是因为与其他约定不同的是,这个方法的实现是在Any类中定义的,这也解释了为什么你不需要将它标记为operator,Any中的基本方法就已经标记了,而且函数的operator修饰符也适用于所有实现或者重写它的方法。而且equals不能实现为扩展函数,因为继承自Any类的实现始终优先于扩展函数。
排序运算符:compareTo
在java中类可以实现Comparable接口,以便在比较值的算法中使用。接口中定义的compareTo方法用于确定一个对象是否大于另一个对象。kotlin中支持同样的接口,但接口中定义的compareTo方法可以按约定使用,比较运算符的使用将被转换为compareTo,且compareTo的返回类型必须为Int。p1<p2等价于p1.compareTo(p2)<0,其他比较运算符的运算方式也是完全一样的。

要注意如何使用kotlin标准库中的compareValuesBy函数来简洁地实现compareTo方法。这个函数接收用来计算比较值的一系列回调,按顺序依次调用回调方法,两两一组分别做比较,并返回结果。如果值不同则返回比较结果,相同则继续调用下一个,如果没有更多回调来调用则返回0。回调函数可以像lambda一样传递,也可以作为属性引用传递

集合与区间的约定
通过下标来访问元素:“get"和"set”
在kotlin中可以用类似java中数组的方式使用方括号来访问map中的元素,也可以用同样的运算符来改变一个可变list的元素

在kotlin中,下标运算符是一个约定。使用下标运算符读取元素会被转换为get运算符方法的调用,写入元素将调用set

x[a,b]=x.get(a,b)
get的参数可以是任何类型,而不只是Int。当你对map使用下标运算符时,参数类型是键的类型,它可以是任何类型,还可以定义具有多个参数的get方法,比如你要实现一个类来表示二维数组或者矩阵。如果要使用不同的键类型访问集合,也可以使用不同的参数类型定义多个重载的get方法

x[a,b]=c x.set(a,b,c)
"in"的约定
in运算符用于检查某个对象是否属于集合,相应的函数叫做contains。in右边的对象将会调用contains函数,左边的对象将会作为函数入参 a in c=c.contains(a)
rangeTo的约定
要创建一个区间使用..语法。…运算符是调用rangeTo的一个简洁方法start..end=start.rangeTo(end)
rangeTo返回一个区间,你可以为自己的类定义这个运算符。但如果该类实现了Comparable接口就不需要了,你可通过kotlin标准库创建一个任意可比较元素的区间,这个库定义了可以用于任何可比较元素的rangeTo函数

这个函数返回一个区间,可以用来检测其它一些函数是否属于它。rangeTo的优先级低于算术运算符
注意,表达式0…n.forEach{print(it)}不会被编译,因为必须把区间表达式括起来才能调用它的方法:(0..n).forEach{print(it)}
在for循环中使用"iterator"的约定
for循环中可以使用in运算符,和做区间检查一样。但这种情况下它的含义是不同的,现在它被用来执行迭代。这意味着一个诸如for(x in list){…}将被转换成list.iterator() 的调用,然后像在java中一样在它上面重复调用hasNext和next方法。在kotlin中这也是一种约定,这意味着iterator方法可以被定为扩展函数,这就解释了为什么可以遍历一个常规的java字符串:标准库已经为CharSequence定义了一个扩展函数iterator,而它是String的父类
为自己的类定义iterator方法

请注意如何在自定义区间类型上定义iterator方法:使用LocalDate作为类型参数。如上一节所示,rangeTo库函数返回一个CloseRange的实例,并且ClosedRange< LocalDate>的iterator扩展允许在for循环中使用区间的实例
边栏推荐
- Methods of using arrays as function parameters in shell
- 【点云处理之论文狂读经典版8】—— O-CNN: Octree-based Convolutional Neural Networks for 3D Shape Analysis
- 数字化管理中台+低代码,JNPF开启企业数字化转型的新引擎
- String splicing method in shell
- On February 14, 2022, learn the imitation Niuke project - develop the registration function
- With low code prospect, jnpf is flexible and easy to use, and uses intelligence to define a new office mode
- 状态压缩DP AcWing 291. 蒙德里安的梦想
- MySQL installation and configuration (command line version)
- Digital management medium + low code, jnpf opens a new engine for enterprise digital transformation
- How to check whether the disk is in guid format (GPT) or MBR format? Judge whether UEFI mode starts or legacy mode starts?
猜你喜欢

【点云处理之论文狂读前沿版9】—Advanced Feature Learning on Point Clouds using Multi-resolution Features and Learni

【点云处理之论文狂读经典版12】—— FoldingNet: Point Cloud Auto-encoder via Deep Grid Deformation

LeetCode 535. TinyURL 的加密与解密

传统办公模式的“助推器”,搭建OA办公系统,原来就这么简单!

我們有個共同的名字,XX工

Discussion on enterprise informatization construction

Excel is not as good as jnpf form for 3 minutes in an hour. Leaders must praise it when making reports like this!

Find the combination number acwing 885 Find the combination number I

Install third-party libraries such as Jieba under Anaconda pytorch

【点云处理之论文狂读经典版7】—— Dynamic Edge-Conditioned Filters in Convolutional Neural Networks on Graphs
随机推荐
Uc/os self-study from 0
Sword finger offer II 091 Paint the house
Discussion on enterprise informatization construction
Six dimensional space (C language)
The method of replacing the newline character '\n' of a file with a space in the shell
[point cloud processing paper crazy reading classic version 12] - foldingnet: point cloud auto encoder via deep grid deformation
LeetCode 241. Design priorities for operational expressions
精彩回顾|I/O Extended 2022 活动干货分享
LeetCode 324. 摆动排序 II
Instant messaging IM is the countercurrent of the progress of the times? See what jnpf says
2022-2-14 learning xiangniuke project - generate verification code
AcWing 786. 第k个数
LeetCode 30. Concatenate substrings of all words
剑指 Offer II 091. 粉刷房子
[point cloud processing paper crazy reading classic version 14] - dynamic graph CNN for learning on point clouds
干货!零售业智能化管理会遇到哪些问题?看懂这篇文章就够了
LeetCode 324. Swing sort II
Using variables in sed command
LeetCode 715. Range 模块
【毕业季|进击的技术er】又到一年毕业季,一毕业就转行,从动物科学到程序员,10年程序员有话说