Kotlin学习笔记十六、《Kotlin学习笔记六、函数运用》的补充:扩展方法

我们知道,在Java里面,没有扩展方法这个概念,只有utils工具类,我们需要实现Java本身没有提供的功能API的时候,我们就只有自己写工具类来实现。

但kotlin里面。我们是可以基于系统提供的API对系统功能进行扩展。当然这样的扩展只对本工程有效。

扩展方法的实现形式:正常书写的方法名前加上“receiver”,也就是“要判断的对象的类名.”。

比如下面的示例,我们要判断某个String字符串的是否为空:String.isEmpty(msg:String)。其中,“String.”就是我们“要判断的对象的类名.”,“isEmpty”就是方法名:

fun String.isEmptyOrNull(): Boolean {
    return this.isNullOrEmpty() || this.trim().isEmpty()
}

使用的时候很简单,我们直接这样调用即可:

println("${"sdfghj".isEmptyOrNull()}")

运行结果如下:
在这里插入图片描述

再来看看一个字符串填充的扩展类:

fun String.margin(start: Int = 1, end: Int = 5, char: Char = '*', separator: CharSequence = ","): String {
//这里的(start .. end)形成一个从start到end的前后闭合的一个闭区间;
//(start .. end).joinToString(separator):表示在这个闭合区间内,循环产生对象,每隔对象之间被separator隔开;
//而这个对象则由后面的“{}”大括弧里面的内容指定,具体见下面大括弧里面的注释说明:
val padding = (start..end).joinToString(separator) {
//        //这里的it就表示在(start .. end)闭区间内循环产生的每个对象,比如闭区间为(1 .. 5),那么循环产生的每隔对象分别为1、2、3、4、5
//        it.toString()
//        //在(start .. end)闭区间内循环产生的每个对象由外界指定,比如这里指定为char,默认为“*”
        char.toString()
//        //在(start .. end)闭区间内循环产生的每个对象为调用该方法的字符串本身,比如外界调用该方法的字符串为"abc",那么产生的字符串即为“abc”
//        this
    }
   
    return "${padding}${this}${padding}"
}

注意事项以及含义解说,注释里面写得很清楚,这里就不再多说。

假设字符串"abc"以如下方式调用:“966487”.margin(5, 10, separator = “”),那么上面的padding变量对应的字符串分别为:

    1、it.toString()---->>>56789109664875678910
    2、char.toString()---->>>******966487******
    3、this---->>>966487966487966487966487966487966487966487966487966487966487966487966487966487

使用的时候调用方式如下:

println("966487".margin(5, 10, separator = ""))

因此扩展方法还是比较简单。我们现在再来说对自定义的某个类扩展属性property,直接上代码:
自定义的类:

class PoorGuy : Guy{
    var mWealth:Double = 0.0
}

按惯例,我们先扩展一个方法:
对于PoorGuy这个类,我们可以为他定义扩展方法,在实现上,跟我们前面的扩展String.kt的方法没有区别;

fun PoorGuy.noMoney() {
    println("I'm very very poor, I haven't any money to life")
}

我们还可以对PoorGuy这个类扩展属性property:
1、由于在kotlin里面,属性property <==>java里面的backing field + get + set,但是自定义的扩展属性是没有feilding存在的,因此我们不能用feilding来接收set方法里面的参数;
2、但是我们有曲折的实现方式:我们可以在PoorGuy里面创建一个public变量,用它来接受和返回变量值;
3、但是要注意我们创建的这个变量必须是public的,否则无法获取到。

var PoorGuy.wealth: Double
    get() {
        return mWealth
    }
    set(value) {
        mWealth = value
    }

除了扩展属性里面没有field之外,interface接口也是没有的:
1、我们知道kotlin里面,接口内部也是可以定义自有的属性property和具体方法实现的。
2、当我们定义属性property时,需要注意:接口 也是没有field的,因此他的get/set方法并没有太多的实际意义。
3、因为get得到的是一个具体的固定值,没法修改;有因为接口不存在field状态,导致不能通过field来存储set方法的值value。
4、另外,定义的get/set方法并不能被复写。

interface Guy{
    var guyWealth:Double
        get() {
            return 0.0
        }
        set(value) {
            当我们像下面这样写set方法的时候,IDE就会报错,提示:Property in an interface cannot have a backing field
//            field = value
        }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值