Kotlin对象: 方法和属性扩展

先定义一个类:

package com.init.demo.extend

class Say{

    fun  sayHi() = println("Hi")
    fun  sayBye() = println("Bye")



}

测试类:

package com.init.demo.extend

fun main(args: Array<String>) {
    val say = Say()
    say.sayGreat()
    2.sayPlay()

    val mmo = mutableMapOf<String, Int?>()
    mmo.addNotNull("one",2)
    mmo.addNotNull("two",null)
    mmo.addNotNull("three",3)

    println(mmo)
}

/**
 * 类的方法和属性都可以扩展
 * 扩展类Say的方法和属性
 * 不一定是在内部扩展,也可以在其它类中扩展
 * eg:如下
 */
fun Say.sayGreat() = println("Great!")
fun Say.sayLove() = println("Love!")
fun Say.sayHah() = println("Hah!")
fun Say.sayPlay() = println("Play!")

fun Int.sayPlay() = println("Play!")

/**
 * 扩展不能真正地修改它们所扩展的类。
 * 通过定义一个扩展,你并没有在一个类中插入新成员,
 * 仅仅可以通过该类型的变量用点表达式去调用这个新函数。
 * 所扩展的函数并不是将它们变成该类的方法,而是同一种特殊的方式定义一个函数,
 * 可以通过“实例名.该实例所属类的扩展函数(参数)”来执行它们。
 * 并且扩展函数是静态解析的。这意味着调用的扩展函数是由函数调用所在的表达式的类型决定的,
 * 而不是由表达式运行时求值结果决定的。这和Java的多态机制是完全相反的。
 */
fun MutableMap<String,Int?>.addNotNull(key:String,value:Int?){
    if(value !=null){
        this[key] = value
    }
}

实例类举证1:

package com.init.demo.extend

class DemoExtendPerson {
    var name: String = ""
    var age: Int = 0
    fun printInfomation() = println("name:$name")
}

//fun  DemoExtendPerson.printInfomation() = println("age:${this.age}")
fun  DemoExtendPerson.printInfomation(count:Int) {
    for (i in 1..count){
        println("age:${this.age}")
    }
}

实例类举证测试1:

package com.init.demo.extend

fun main(args: Array<String>) {
    val demoExtendPerson = DemoExtendPerson()
    demoExtendPerson.age = 20
    demoExtendPerson.name = "小明"
    demoExtendPerson.printInfomation()
    //    输出:name:小明
    /**
     * 修改了扩展方法以后 eg
     * Kotlin 会根据不同的参数选择不同的扩展函数
     * 入股没有参数 就会选择类内部的函数
     * 扩展函数在和内部函数的命名、参数数量和参数类型相同时,
     * 编译器无法区分,会优先选择类内部的函数
     */
    demoExtendPerson.printInfomation(3)
    //    输出:
    /*age:20
    age:20
    age:20*/
}

实例类举证2:

package com.init.demo.extend

class DemoExtendPerson1{
    /**
     * 对属性的扩展也是有局限性的,因为我们扩展属性并不是在类的内部将这个属性插入,
     * 所以不能有初始化器,它们的行为只能由显式提供的ge阳r和se忧er定义。
     * 也就是说,我们不能用构造器对这个属性进行初始化,也不能有初始化器。
     * v a r / v al类名.属性名
     */
    var name: String = ""
    var _age: Int = 0
}

fun  DemoExtendPerson1?.printInfomation() {
    if(this==null){
        println("Sorry,this is null")
    }else{
        println("name:$name,age:$age")
    }
}

/**
 * 如果不初始化,会报error
 * Extension property must have accessors or be abstract 意思是:属性必须初始化
 * 如果不写setter或者getter,会报error
 * Extension property must have accessors or be abstract 意思是:属性必须初始化
 * 调用了初始化器,初始化器会通过属性的幕后字段为其赋初值,
 * 而扩展属性根本就没有幕后字段,因为它根本就不是这个类内部定义的成员。
 *  幕后字段field:unresolved reference: field
 *  扩展属性没有幕后字段
 * 对扩展属性赋值的时候,其实是对中间变量进行赋值,
 * 如果想对扩展属性取值,骑士也是对中间变量进行取值
 */
var DemoExtendPerson1.age: Int
    get() = this._age
    set(value) {
//        field = value
        this._age = value
    }

实例类举证测试2:

package com.init.demo.extend

fun main(args: Array<String>) {

    val  person:DemoExtendPerson1? = null
    println(person.printInfomation())

    val demoExtendPerson1:DemoExtendPerson1? = DemoExtendPerson1()
    demoExtendPerson1?.name = "SHEN"
    /**
     * 把一些重复的代码封装到扩展属性的访问中,有利于维护代码
     */
    demoExtendPerson1?.age = 12
    demoExtendPerson1?.printInfomation()

    //最后输出:name:SHEN,age:12
    
}

对于扩展函数:只能访问类声明下的函数:

package com.init.demo.extend

open class DemoExtendA{
    open fun printHello() = println("Hello,A")
}

class  DemoExtendB:DemoExtendA(){

    override fun printHello() = println("Hello,B")
}

fun DemoExtendA.printA() = println("Hello,A")
fun DemoExtendB.printB() = println("Hello,B")
/**
 * 对于扩展函数:只能访问类声明下的函数
 */
fun main(args: Array<String>) {
    val ele:DemoExtendA = DemoExtendB()
    ele.printA()
    /**
     * ele 不能访问printB方法,因为类声明下的函数没有printB函数
     * 如果要访问,会报error:
     * //Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
     * public fun DemoExtendB.printB(): Unit defined in com.init.demo.extend in file DemoExtendA.
     */
//    ele.printB()
    /**
     * 类中的方法时动态解析的,声明方法是静态解析的
     */
    ele.printHello()
    val ele1 = DemoExtendB()
    ele1.printB()
}

最后,

package com.init.demo.extend

class Fruits(names: List<String>) {
    val names: List<String> = names

    fun printInfomation() = names.forEach { print("\t${it}") }
}

class Box(size: Int) {
    val size: Int = size

    fun Fruits.printALl() {
        this@Box.printInfomation()
    }

    fun haveFruits(f: Fruits) {
//        println("I am  a box,size is $size")
//        println("I have fruits:")
        printInfomation()
        f.printALl()
    }

    fun printInfomation() {
        println("I am  a box,size is $size")
        println("I have fruits:")
    }


}

fun main(args: Array<String>) {
    val fruits = Fruits(listOf("Banana", "Apple", "Watermelon"))
    val box = Box(15)
    /**
     *修改haveFruits和添加Box内部方法printInfomation前 的输出:
     *   I am  a box,size is 15
     *   I have fruits:
     *   Banana    Apple  Watermelon
     * 修改haveFruits和添加Box内部方法printInfomation后 的输出
     *   I am  a box,size is 15
     *   I have fruits:
     *   I am  a box,size is 15
     *   I have fruits:
     */
    box.haveFruits(fruits)

    val list = mutableListOf<Int>(1, 2, 3)
    swapindexFromList(list, 0, 2)
    println("List对象两个圆度的位置交换:"+list)

    val  list1=  mutableListOf<Int>(1 ,  2, 3)
    list1.swapindexFromList1  (0,  2)
    println("List对象两个圆度的位置交换方法扩展:"+list1)

    /*输出:
    List对象两个圆度的位置交换:[3, 2, 1]
    List对象两个圆度的位置交换方法扩展:[3, 2, 1]*/
}

/**
 * List对象两个圆度的位置交换
 */
fun swapindexFromList(list: MutableList<Int>, indexl: Int, index2: Int) {
    val temp = list[indexl]

    list[indexl] = list[index2]
    list[index2] = temp
}
/**
 * List对象两个圆度的位置交换方法扩展
 */
fun MutableList<Int>.swapindexFromList1(indexl: Int, index2: Int) {
    val temp = this[indexl]
    this[indexl] = this[index2]
    this[index2] = temp
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值