kotlin学习(6)运算符重载和其他约定
约定
在Kotlin中,可以调用自己代码中定义的函数,来实现语言结构。这戏功能与特定的函数命名相关,例如,在你的类中定义了一个名为plus的特殊方法,那么按照约定,就可以在该类的实例上使用 + 运算符,因此,我们把这种技术称为“约定”。
重载运算符
/* *这里给一个类添加了plus方法来重载 + 运算符 */ data point(val X:Int,val Y:Int){ //operator修饰符是声明这个方法是用来重载的 operator fun plus(other:point): point { return point(this.X+other.X,this.Y+other.Y) } } //重载之后,point对象就可以直接使用+运算符来操作两个对象了 fun main(args: Array<String>) { val a= point(1,1) val b= point(2,3) println(a+b) }
可重载的二元运算符
表达式 | 函数名 |
a * b | times |
a / b | div |
a % b | mod |
a + b | plus |
a - b | minus |
如果重载 + 或 * 计算的两边类型不同的话,那么不支持交换性,需要额外定义一个函数。
可重载的一元运算符
表达式 | 函数名 |
+a | unaryPlus |
-a | unaryMinus |
!a | not |
++a,a++ | inc |
--a,a-- | dec |
可重载的比较运算符
equals和compareTo
集合与区间的约定
通过下标来访问元素:“get“和”set“
//这里使用了扩展函数实现get约定 operator fun point.get(index : int): Int{ return when(index){ 0 -> x 1 -> y else -> throw IndexOutOfBoundsException("Invalid coordinate $ index") } } //重载set operator fun point.set(index : int,value : Int): Int{ return when(index){ 0 -> x = value //根据对应的index来修改值 1 -> y = value else -> throw IndexOutOfBoundsException("Invalid coordinate $ index") } } >>>val p=point(10,20) >>>println(p[1]) 20
in的约定,相对应的函数叫做contains
//使用in来检查点是否在矩形区域内 data class Rectangle(val upperLeft:point, val lowerRight:point) operator fun Rectangle.contains(p:point):Boolean{ //until构建了一个开区间 return p.x in upperLeft.x until lowerRight.x && p.y in upperLeft.y until lowerRight.y }
//rangeTo的约定 1..10 operator fun <T: Comparable<T>> T.rangeTo(that: T): ClosedRange<T> //在for循环中使用iterator的约定,这让迭代字符串成为可能 operator fun CharSequence.iterator(): CharIterator >>>for (c in "abc")
解构声明和组件函数
解构声明允许展开单个复合值,并使用它来初始化多个单独的变量
>>>val p = point(10, 20) >>>val (x,y) = p >>>println(x) 10 >>>printlb(y) 20
对于数据类,编译器为每个在主构造方法中声明的属性生成一个componentN函数,下面展示如何手动为非数据类声明这些功能:、
//结构声明,可以在调用函数后轻松的展开一个对象,使用它的值 class point(val x: Int, val y: Int){ operator fun component1() = x operator fun component2() = y }
此外,还可以用解构声明来遍历map for((key, value) in map){ println("$key -> $value") }
委托属性(不全)
//使用委托来实现懒汉式初始化(不调用不赋值,调用时才初始化) fun loadEmails():Int{ println("Load emails") return 1 } class Person(val name:String){ val emails by lazy{ loadEmails() } } >>>println(Person().emails) Load emails 1