疯狂kotlin讲义连载之运算符和表达式——运算符重载

386 阅读4分钟

正如第一节所介绍的,Kotlin的运算符都是靠特定名称的方法在支撑,因此只要为重载这些名称的方法,我们就可以为任意类添加这些运算符。

重载操作符的方法需要用operator修饰符进行标记。

3.4.1 重载单目前缀运算符

3.1
已经给出了单目前缀运算符对应的函数名,因此只要我们为任意类定义名为 unaryPlus()unaryMinus()not(),且以operator修饰的方法,那么程序即可对该类的实例使用+-!等单目前缀运算符。例如如下程序。

程序清单:codes\03\3.4\UnaryTest.kt

data class Data(val x: Int, val y: Int){

//Data类定义一个unaryMinus()方法

operator fun unaryMinus(): Data {

return Data(-x, -y)

}

}

//以扩展方法的形式为Data类定义not()方法

operator fun Data.not(): Data {

return Data(-x, -y)

}

fun main(args: Array<String>) {

val d = Data(4, 10)

println(-d) //输出Data(x=-4, y=-10)

println(!d) //输出Data(x=-4, y=-10)

}

上面程序中定义了一个非常简单的Data类,并在该类中定义了一个operator修饰的unaryMinus()方法,该方法返回一个将Dataxy两个属性取反的Data实例,这意味着我们可以对Data实例应用-这个单目前缀运算符。

提示:关于Kot定义类、扩展方法的知识,请参考本书第5.6节内容。

此外上面程序还以扩展方法的形式为Data类定义了一个not()方法,该方法同样返回一个将Dataxy两个属性取反的Data实例,这意味着我们可以对Data实例应用!这个单目前缀运算符。

上面程序main()方法的最后两行对Data对象应用了-!这两个运算符,这两个表达式的输出结果是一样的。

3.4.2 重载自加和自减

3.2已经给出了自加、自减运算符对应的函数名,因此只要我们为任意类定义名为 inc()dec(),且以operator修饰的方法,那么程序即可对该类的实例使用++--运算符。例如如下程序。

程序清单:codes\03\3.4\SelfInc.kt

data class Data(val x: Int, val y: Int){

//Data类定义一个inc()方法

operator fun inc(): Data {

return Data(x + 1, y + 1)

}

}

//以扩展方法的形式为Data类定义dec()方法

operator fun Data.dec(): Data {

return Data(x - 1, y - 1)

}

fun main(args: Array<String>) {

var d = Data(4, 10)

println(d++) //先用、再自加,输出Data(x=4, y=10)

println(d) //输出自加后的dData(x=5, y=11)

var dd = Data(9, 20)

println(--dd) //先自减,再用,输出Data(x=8, y=19)

println(dd) //输出自加后的ddData(x=8, y=19)

}

上面程序以普通方法和扩展方法的形式为Data类定义了inc()dec()两个方法,并使用operator修饰了这两个方法,因此接下来程序即可对Data实例使用自加、自减运算符执行计算。

当程序对Data对象使用自加运算符时,该对象的xy两个属性都会加1;当程序对Data对象使用自减运算符时,该对象的xy两个属性都会减1。至于++--放在变量前面和后面的差异,其实与Java语言中++--放在变量前面和后面的差异完全一样,此处不再深入展开介绍。

3.4.3 重载双目算术运算符

3.3已经给出了双目算术运算符对应的函数名,因此只要我们为任意类定义名为plus()minus()times()div()rem()rangeTo()、且以operator修饰的方法,那么程序即可对该类的实例使用+-*/%..这些运算符。例如如下程序。

程序清单:codes\03\3.4\ArthimethicTestKt.class.kt

data class Point(val x: Int, val y: Int){

//Point类定义一个minus()方法

operator fun minus(target: Point): Double{

return Math.hypot((this.x - target.x).toDouble()

, (this.y - target.y).toDouble())

}

}

//以扩展方法的形式为Point类定义times()方法

operator fun Point.times(target: Point): Int {

return Math.abs(this.x - target.x) *

Math.abs(this.y - target.y)

}

fun main(args: Array<String>) {

var p1 = Point(4, 10)

var p2 = Point(5, 15)

var distance = p1 - p2;

println("p1p2的距离为:${distance}")

var area = p1 * p2

println("p1p2围成矩形的面积为:${area}")

}

上面程序中定义了一个Point类,接下来程序在Point类中定义了一个minus()方法,该方法用于计算两个Point之间的距离;此外,程序还通过扩展方法的形式为Point定义了一个times()方法,该方法用于计算两个Point所围成的矩形的面积。

只要为Point类定义了minus()times()两个方法,接下来程序即可用-*两个运算符来计算两个运算符之间的距离、所围成矩形的面积,如上程序所示。

以上内容节选自《疯狂Kotlin讲义》:一本让您最直接认识Kotlin的疯狂讲义


本书即将于2017年11月发售 敬请期待

往期连载


相关书籍《疯狂Android讲义》item.jd.com/11689014.ht…