Kotlin学习之扩展和运算符重载

1、扩展函数

扩展函数表示即使在不修改某个类的源码的情况下,仍然可以打开这个类,向该类添加新的函数。

其语法结构非常简单,如下所示:

fun ClassName.methodName(param1: Int, param2: Int): Int {
      return 0
}

我们先来看一个示例

定义一个lettersCount方法,用于统计字符串中包含字母的数量

fun lettersCount(str: String): Int {
        var count = 0
        for (char in str) {
            if (char.isLetter()) {
                count++
            }
        }
        return count
    }

然后是调用

val str = "ABC123xyz!@#"
val count =lettersCount(str)

接下来我们来试一下扩展函数的写法

只需在一个kotlin file 文件中添加以下函数

fun String.lettersCount(): Int {
        var count = 0
        for (char in this) {
            if (char.isLetter()) {
                count++
            }
        }
        return count
    }

我们就可以在其他地方使用扩展函数得使用了

val str = "ABC123xyz!@#"
str.lettersCount();

就和这个方法就是String的方法一样


2、扩展函数是静态解析的

扩展函数是静态解析的,并不是接收者类型的虚拟成员,在调用扩展函数时,具体被调用的的是哪一个函数,由调用函数的的对象表达式来决定的,而不是动态的类型决定的:

open class C

class D: C()

fun C.foo() = "c"   // 扩展函数 foo

fun D.foo() = "d"   // 扩展函数 foo

fun printFoo(c: C) {
    println(c.foo())  // 类型是 C 类
}

fun main(arg:Array<String>){
    printFoo(D())
}

实例执行输出结果为:

c

若扩展函数和成员函数一致,则使用该函数时,会优先使用成员函数。

class C {
    fun foo() { println("成员函数") }
}

fun C.foo() { println("扩展函数") }

fun main(arg:Array<String>){
    var c = C()
    c.foo()
}

实例执行输出结果为:

成员函数

3、扩展一个空对象

在扩展函数内, 可以通过 this 来判断接收者是否为 NULL,这样,即使接收者为 NULL,也可以调用扩展函数。例如:

fun Any?.toString(): String {
    if (this == null) return "null"
    // 空检测之后,“this”会自动转换为非空类型,所以下面的 toString()
    // 解析为 Any 类的成员函数
    return toString()
}
fun main(arg:Array<String>){
    var t = null
    println(t.toString())
}

实例执行输出结果为:

null

扩展属性

除了函数,Kotlin 也支持属性对属性进行扩展:

val <T> List<T>.lastIndex: Int
    get() = size - 1
 

扩展属性允许定义在类或者kotlin文件中,不允许定义在函数中。初始化属性因为属性没有后端字段(backing field),所以不允许被初始化,只能由显式提供的 getter/setter 定义。

val Foo.bar = 1 // 错误:扩展属性不能有初始化器

扩展属性只能被声明为 val。


4、伴生对象的扩展

如果一个类定义有一个伴生对象 ,你也可以为伴生对象定义扩展函数和属性。

伴生对象通过"类名."形式调用伴生对象,伴生对象声明的扩展函数,通过用类名限定符来调用:

class MyClass {
    companion object { }  // 将被称为 "Companion"
}

fun MyClass.Companion.foo() {
    println("伴随对象的扩展函数")
}

val MyClass.Companion.no: Int
    get() = 10

fun main(args: Array<String>) {
    println("no:${MyClass.no}")
    MyClass.foo()
}

实例执行输出结果为:

no:10
伴随对象的扩展函数

5、运算符重载

Kotlin的运算符重载允许我们让任意两个对象进行相加,或者是进行更多其他的运算操作。

这里以加号运算符为例,如果想要实现让两个对象相加的功能,那么它的语法结构如下:

class Obj {
      operator fun plus(obj: Obj): Obj {
            // 处理相加的逻辑
      }
}

接下来我们来实现下来两个Money对象得相加

首先常见Money类

class Money(val value: Int)

接下来就重载Money得加法运算

class Money(val value: Int) {
    operator fun plus(money: Money): Money {
        val sum = value + money.value
        return Money(sum)
    }
}

那么我们就可以用

val money1 = Money(5)
val money2 = Money(10)
val money3 = money1 + money2
println(money3)

Snipaste_2021-01-09_12-12-39

同时Kotlin允许我们对同一个运算符进行多重重载,我们再实现一个Money与整形数的加法

class Money(val value: Int) {
    operator fun plus(money: Money): Money {
        val sum = value + money.value
        return Money(sum)
    }
    operator fun plus(newValue: Int): Money {
        val sum = value + newValue
        return Money(sum)
    }
}

测试一下

val money1 = Money(5)
val money2 = Money(10)
val money3 = money1 + money2
val money4 = money3 + 20
println(money4)

Snipaste_2021-01-09_12-13-06

参考自 第一行代码3,以及菜鸟教程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值