Kotlin操作符重载的方法
导读:本文共5178字符,通常情况下阅读需要17分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要: 算数运算操作符重载在kotlin中我定义一个类dataclassPoint(valx:Int,valy:Int)然后实例化两个对象valp1=Point(3,5)valp2=Point(5,7)想表示p1的元素x加上p2的元素x,p1的元素y,加上... ...
目录
(为您整理了一些要点),点击可以直达。
算数运算操作符重载
在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中提供了以下操作符的重载. 只需要实现对应的方法即可。
之前我们定一个了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--同样支持运算符重载。仅仅需要重写下面的操作符函数即可
举个例子
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方法.
这里看下//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中我们可以使用类似于操作数组的方法操作集合,例如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操作符
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是变量的位置.
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操作符重载的方法的详细内容,希望对您有所帮助,信息来源于网络。