Kotlin操作符重载的方法(kotlin,开发技术)

时间:2024-05-05 14:40:39 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

算数运算操作符重载

在kotlin中我定义一个类

dataclassPoint(valx:Int,valy:Int)

然后实例化两个对象

valp1=Point(3,5)valp2=Point(5,7)

想表示p1的元素x加上p2的元素x,p1的元素y,加上p2的元素y.然后输出一个p3.

valp3=Point(p1.x+p2.x,p2.y+p2.y)

以上这种写法没有任何问题。不过我们可以利用Kotlin扩展函数简化上面的操作,我们给Point增加一个plus,并附加operator关键字。(增加operator的关键字是为了区分plus并不是一个普通的成员方法)

dataclassPoint(valx:Int,valy:Int){operatorfunplus(other:Point):Point{returnPoint(x+other.x,y+other.y)}}

接下来再来实现上面的需求.

valp3=p1+p2

这样表达起来更简洁了。 另外我们可以把plus作为Point的扩展方法

dataclassPoint(valx:Int,valy:Int)operatorfunPoint.plus(other:Point):Point{returnPoint(x+other.x,y+other.y)}

这种场景适用于Point存在于一个三方库,我们并能修改其中的内容. Kotlin中提供了以下操作符的重载. 只需要实现对应的方法即可。

Kotlin操作符重载的方法

之前我们定一个了plus,参数是Point,实际上对于个操作符重载并不局限于同一种类型,接下来我们来定一个times,允许你去扩展Ponit.

dataclassPoint(valx:Int,valy:Int)operatorfunPoint.times(scale:Double):Point{returnPoint((x*scale).toInt(),(y*scale).toInt())}funmain(args:Array<String>){valp=Point(10,20)println(p*1.5)}

注意kotlin不支持交换性,例如我这里写成1.5 * p这里是不允许的。除非你去定一个

operatorfunDouble.times(p:Point):Point

返回类型同样也可以不是同一个类型,例如, 定义一个对char类型重载*操作符重复count后返回一个string.

operatorfunChar.times(count:Int):String{returntoString().repeat(count)}funmain(args:Array<String>){println('a'*3)}

复合运算操作符重载

我们在编程过程中通常会去把这种写法p = p + p1 写成 p += p1 这种简化写法,在kotlin中同样也支持这种+=操作符自定义操作。这种自定义运算操作符在什么场景下使用呢? 举个例子,我们定义集合

valnumbers=ArrayList<Int>()numbers+=42println(numbers[0])

以上写法会感觉更加简洁。 我们在集合中定义操作符重载方法plusAssign(这里还有minusAssign,timesAssign等等)

operatorfun<T>MutableCollection<T>.plusAssign(element:T){this.add(element)}

不过kotlin-stblib库已经帮你实现好了关于集合的类似操作. 在集合中+,-会累加集合原始后返回一个新的集合,如果使用+=,-=, 集合是mutable,会在本集合直接修改内容,如果集合是read-only,会返回一个拷贝后的修改集合。(这意味着如果集合是read-only,它的声明必须要是var, 不然它不能接受新返回拷贝后的修改集合). 你可以使用单独的元素或者集合(类型必须一致)进行复合运算符操作和算数运算符.

vallist=arrayListOf(1,2)list+=3valnewList=list+listOf(4,5)println(list)result:[1,2,3]println(newList)result:[1,2,3,4,5]

一元运算操作符重载

我们在编程过程中使用类似++a, a++, --a, a--同样支持运算符重载。仅仅需要重写下面的操作符函数即可

Kotlin操作符重载的方法

举个例子

operatorfunBigDecimal.inc()=this+BigDecimal.ONEfunmain(args:Array<String>){varbd=BigDecimal.ZEROprintln(bd++)println(++bd)}

这里注意到我只定一个inc(),同时也是支持bd++和++bd.

比较操作符重载

kotlin中还支持==,!=,>,<操作符重载. 对于==,!=我们重写equals方法. 这里还是拿Point来举栗子

dataclassPoint(valx:Int,valy:Int)

我们这里声明成了data类,这个关键字加上了编译器会自动帮你实现equals方法,我们现在去掉,看看自己去写equals怎么写

classPoint(valx:Int,valy:Int){overridefunequals(obj:Any?):Boolean{if(obj===this)returntrue//1if(obj!isPoint)returnfalsereturnobj.x==x&&obj.y==y}}funmain(args:Array<String>){println(Point(10,20)==Point(10,20))println(Point(10,20)!=Point(5,5))//2println(null==Point(1,2))}

这里我们需要关注一个//1 obj === this,这个===操作符是比较两个对象的引用是否一致,实际上和java中的==是一样的。 之前我们提到的操作符重载都会加上一个operator关键字,这里为什么是override?因为它重写了Any.class的equals方法.

Kotlin操作符重载的方法

这里看下//2!= 其实就是equals结果的取反. 除了=和!=之外这里还有>和<, 通过重写compareTo可以实现

classPerson(valfirstName:String,vallastName:String):Comparable<Person>{overridefuncompareTo(other:Person):Int{returncompareValuesBy(this,other,Person::lastName,Person::firstName)}}funmain(args:Array<String>){valp1=Person("Alice","Smith")valp2=Person("Bob","Johnson")println(p1<p2)}

这里的compareValuesBy顺便说说,它是kotlin-stblib提供的扩展函数

Kotlin操作符重载的方法

集合和区域的约定

在kotlin中我们可以使用类似于操作数组的方法操作集合,例如a[b]这种. 对于其它类,可以自定义操作符实现类似的操作

operatorfunPoint.get(index:Int):Int{returnwhen(index){0->x1->yelse->throwIndexOutOfBoundsException("Invalidcoordinate$index")}}funmain(args:Array<String>){valp=Point(10,20)println(p[1])}

我们对于赋值操作同样也可以通过自定义operator

dataclassMutablePoint(varx:Int,vary:Int)operatorfunMutablePoint.set(index:Int,value:Int){when(index){0->x=value1->y=valueelse->throwIndexOutOfBoundsException("Invalidcoordinate$index")}}funmain(args:Array<String>){valp=MutablePoint(10,20)p[1]=42println(p)}

另外一个知识点是自定义in操作符

Kotlin操作符重载的方法

in对于的contains函数,判断一个元素是否属于一个范围里.

dataclassPoint(valx:Int,valy:Int)dataclassRectangle(valupperLeft:Point,vallowerRight:Point)operatorfunRectangle.contains(p:Point):Boolean{returnp.xinupperLeft.xuntillowerRight.x&&p.yinupperLeft.yuntillowerRight.y}funmain(args:Array<String>){valrect=Rectangle(Point(10,20),Point(50,50))println(Point(20,30)inrect)println(Point(5,5)inrect)}

迭代运算符重载

我们平时使用的

for(xinlist){...}

将被转换为 list.iterator() 的调用,然后重复调用 hasNext 和 next 方法,就像在 Java 中一样。 请注意,在 Kotlin 中,它也是一种约定,这意味着可以将迭代器方法定义为扩展。这就解释了为什么可以迭代常规 Java 字符串:kotlin-stblib 在 Char-Sequence(String 的超类)上定义了一个扩展函数迭代器:

operatorfunCharSequence.iterator():CharIterator>>>for(cin"abc"){}

其它类型也可以通过自定义iterator实现自己类特定的操作。

importjava.util.Dateimportjava.time.LocalDateoperatorfunClosedRange<LocalDate>.iterator():Iterator<LocalDate>=object:Iterator<LocalDate>{varcurrent=startoverridefunhasNext()=current<=endInclusiveoverridefunnext()=current.apply{current=plusDays(1)}}funmain(args:Array<String>){valnewYear=LocalDate.ofYearDay(2017,1)valdaysOff=newYear.minusDays(1)..newYearfor(dayOffindaysOff){println(dayOff)}}

解构声明

这个操作可以分解一个对象中成员,例如

>>>valp=Point(10,20)>>>val(x,y)=p>>>println(x)10>>>println(y)20

解构声明看起来有点像变量声明,不过它组合了多个变量值。实际上它在kotlin中也属于自定义操作符.去解构多个变量需要定义componentN,N是变量的位置.

Kotlin操作符重载的方法

classPoint(valx:Int,valy:Int){operatorfuncomponent1()=xoperatorfuncomponent2()=y}

对于data类,解构已经帮你声明好了 另外解构声明还可以用在循环中

funprintEntries(map:Map<String,String>){for((key,value)inmap){println("$key->$value")}}funmain(args:Array<String>){valmap=mapOf("Oracle"to"Java","JetBrains"to"Kotlin")printEntries(map)}

Map中包含了扩展方法component1,component2返回key和value. 实际上你可以将上面的循环部分翻译成

for(entryinmap.entries){valkey=entry.component1()valvalue=entry.component2()//...}
 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:Kotlin操作符重载的方法的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:react中hook的概念是什么下一篇:

5 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18