kotlin第六天:解构、运算符重载

解构声明

解构声明,允许你展开单个复合值,并且使用它来初始化多个单独的变量。

val p = Point(10,20)
val(x,y) = p

事实上,解构声明用到了约定的原理。要在解构声明中初始化每个变量,
将调用名为 componentN 的函数 ,其中 N 是声明中变量的位置.
上面的例子实际是:

val x = p.component1()
val y = p.component2()

那么要支持解构声明,对于类型有什么要求呢
1、对于数据类,编译器为每个在主构造方法中声明的属性生成一个componentN函数
2、对于非数据类需要我们自己手动添加

class Point(val x :Int,val y:Int){
    operator fun component1() = x
    operator fun component2() = y

}

当然,不可能定义无限数量的 componentN 函数,这样这个语 法就可以与任 意数量的集合一 起工作,但这也没用 。标准库只 允许使用此语 法来访问一个对象的 前五个元素

使用场景一:函数返回多个值

解构声明主要使用场景之一,是从一个函数返回多个值,这个非常有用。如果要这样做,可以定义一个数据类来保存返回所需的值,并将它作为函数的返回类型。在调用函数后,可以用解构声明的方式,来轻松地展开它,使用其中的值。
fun main(args: Array<String>) {
    val (name,ext)= spliteFileName("example.kt")
    println(name)
    println(ext)
}

data class NameComponents(val name:String,val extension:String)

fun spliteFileName(fullName:String):NameComponents{
    val result = fullName.split('.',limit = 2)
    return NameComponents(result[0],result[1])
}

使用场景二:循环迭代

fun printMap(map:Map<String,String>){
    for((key,value) in map){
        println("key:$key,value:$value")
    }
}

其实只要是定义变量的地方,就可以使用解构声明

运算符重载

重载二元算术运算

基本语法

先看一个例子:

data class Point(val x :Int,val y:Int){
    operator fun plus(other:Point):Point{
        return Point(x+other.x,y+other.y)
    }
}
fun main(args: Array<String>) {
    val p1 = Point(10,20)
    val p2 = Point(30,40)
    val p3= p1+p2
    println(p3)
}
//输出
//Point(x=40, y=60)

这个是重载“+”运算符;
注意三点:
1、使用operator关键字修饰plus函数;用于运算符重载的所有函数都必须用该关键字标记
2、由于重载的是“+”运算符,所以函数名叫plus;kotlin不支持自定义运算符,对于已有的运算符也有其对应的名字

表达式函数名
a*btimes
a/bdiv
a%bmod
a+bplus
a-bminus

3、自定义运算符的优先级与标准数字型的运算符有着相同的优先级;即:*、/、%相同优先级,高于+、-优先级

运算符函数声明为扩展函数

除了把这个运算符声明为一个成员函数外, 也可以把它定义为一个扩展函数

operator fun Point.plus(a:String):String{
    return "$a x = $x,y = $y"
}

运算符函数重载

先看个例子

data class Point(val x :Int,val y:Int){
    operator fun plus(other:Point):Point{
        return Point(x+other.x,y+other.y)
    }
}

fun main(args: Array<String>) {
    val p1 = Point(10,20)
    val p2 = Point(30,40)
    val p3= p1+p2
    println(p1+"测试")
    println(p3)

}

operator fun Point.plus(a:String):String{
    return "$a x = $x,y = $y"
}

这个例子体现了几点:
1、运算符函数可以重载
2、不要求两个运算数是相同的类型
3、返回类型可以是任意类型
4、Kotlin运算符不会自动支持交换性,因为有可能返回值类型和原类型都不一样

kotlin 没有位运算符,因此也不允许自定义类型定义他们。
kotlin提供了使用支持中级调用语法的常规函数 ,可以为自定义类型定义相似的函数
shl一一带符号左移
shr-一一带符号右移
ushr一一无符号右移
and一一按位与
or-一一按住或
xor一一按住异或
inv一一按住取反

重载复合赋值运算符

像+=、-=这样的运算符称为:复合赋值运算符

像重载了“+”运算符,如果返回值类型还是原类型,就可以使用+=运算符

var p1 = Point(10,20)
var p2 = Point(30,
p1 +=p2//等价  p1= p1+p2

在一些情况下,定义+=运算 可以修改使用它的变量所引用的对象,但不会重新分配引用

val numbers = ArrayList<Int> ()
numbers += 42 
println(numbers[O])
//输出 42

如果你定义了一个返回值为 Unit,名为 plusAssign 的函数, Kotlin将会在 用到+=运算符的地方调用它。其他二元算术运算符也有相似的函数:minusAssign、 timesAssign 等 。

当你在代码中用到+=的时候,理论上plus和plusAssig口都可能被调用。如果在这种情况下,两个函数都有定义且适用,编译器会报错
解决办法:
一种:可行的解决办法是,替换运算符的使用为普通函数调用。
另一个种:用 val 替 换 var,这样 plusAssign 运算就不再适用。
但一般来说,最好 一 致地设计出新的类: 尽量不要同时给一个类添加 plus 和 plusAssign 运算。如果像前面的 一个示例中 的 Point,这个类是不可变的,那么就应该只提供返回一个新值(如 plus)的运算。 如果一个类是可变的,比如构建器,那么只需要提供 plusAssign 和类似的运算 就够了。

重载一元运算符

一元运算符和与前面的运算符相似

表达式函数名
+aunaryPlus
-aunaryMinus
!anot
++a,a++inc
–a,a–dec

重载比较运算符

比较运算符就是“==,!=,>,<,>=,<=”等符号

等号运算符

在kotlin中== 会转换成equals方法,!=也会转换成equals,只是会取反一下;
==和!= 可用与空运算;

a==b 
//等价于
a?.equals(b)?:b==null

一point为例,看一下equals重写

class Point(val x :Int,val y:Int){
    operator fun plus(other:Point):Point{
        return Point(x+other.x,y+other.y)
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as Point

        if (x != other.x) return false
        if (y != other.y) return false

        return true
    }
}

1、equals不需要operator关键字修饰,增加了override修饰;这是因为这个方法在Any类中定义了;切在Any类中已经标记了operator关键字
2、恒等号=不能被重载,含义和java中的 一样,比较两个对象是不是同一个引用
3、不能把equals函数定义成扩展函数,因为会优先使用Any中的函数,所以就不会使用扩展函数

排序运算符

kotlin中也和java一样,实现Comparable 接口,只是java中实现了Comparable 接口不支持<,>,<=,>=等运算符,kotlin支持。

class Person(val firstName:String,val lastName:String) :Comparable<Person>{
    override fun compareTo(other: Person): Int {
        return compareValuesBy(this,other,Person1::firstName,Person1::lastName)
    }

}
val p1=Person("a","b")
val p2=Person("c","d")
p1>=p2//等价于p1.compareTo(p2)>=0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值