Kt学习06

总结

啊,今天是菜鸟的最后一篇啊,说实话菜鸟的教程雀实有点拉跨。

1 类委托

  • 通过by关键字实现,当然委托都要用by关键字
  • 这个和代理类蛮像的欸,不知道对不对
//1-1.创建接口
interface BasePrint {
    fun print()
}

//1-2.实现接口的被委托类
class BaseImpl(var input: Int) : BasePrint {
    override fun print() {
        println(input)
    }
}

//1-3.通过关键字by  建立委托
class BaseUser(var base: BasePrint) : BasePrint by base

//1-4 使用委托
var base = BaseImpl(12)
BaseUser(base).print()

2 属性委托

  • 属性委托指的是一个类的某个属性值不是在类中直接进行定义,而是将其托付给一个代理类,从而实现对该类的属性统一管理(教程原话)
  • 属性的get和set方法会被委托给委托对象的getValue和setValue方法,val只需要实现getValue,var属性两个都要
//2-1.定义一个被委托的类
//该类需要包含 getValue() 方法和 setValue() 方法,且参数 thisRef 为进行委托的类的对象,prop 为进行委托的属性的对象
class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef,这里委托了${property.name}属性"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$thisRef 的${property.name}属性赋值为$value")
    }
}

//2-2.定义包含属性委托的类
class DelegateUser {
    var info: String by Delegate()//牛逼 这个委托也不用初始化欸
}

    //2-3 使用委托属性
    var user = DelegateUser()
    println(user.info)//访问属性 调用getValue()方法

    user.info = "hello world" //调用setValue()方法
    println(user.info)
    //???? 我辣么打一个user的属性的值呢? 怎么拿啊?你给我一个被委托的属性的名字有个jb用
  • 就是教程有一个问题,使用委托类的时候不知道怎么拿到属性的值欸,上面的property方法没有.value,只能.name拿到名称...

3 延迟属性 Lazy

  • 这个是Kotlin内置的工厂方法提供的委托服务
  • lazy()方法,接受一个 Lambda 表达式作为参数, 返回一个 Lazy <T> 实例的函数,返回的实例可以作为实现延迟属性的委托
  • 两个参数,第一个是第一次使用时候会调用的,第二个是第一次后会调用的
//3-1 定义val属性的lazy委托
class TestLazy {
    val lazyValue: String by lazy {
        println("?????") //这个是第一次调用会跑的地方,以后调用不会走这里

        "hello world"//这是后续运行会调用的地方
    }

    //不能做var属性的委托。报红
    val lazyValue2: Int by lazy {
        var vaule = 1 + 2 //第一次可以使用一个求值等
        vaule
    }
}

val lazyValue: String by lazy {
    println("?????") //这个是第一次调用会跑的地方,以后调用不会走这里

    "hello world"//这是后续运行会调用的地方
}

//不能做var属性的委托。报红
val lazyValue2: Int by lazy {
    var vaule = 1 + 2 //第一次可以使用一个求值等
    vaule
}

 //3-2 使用lazy委托
    println(TestLazy().lazyValue)//第一次
    println(TestLazy().lazyValue)//第二次

    println("------------------")
    //出现差异了
    println(lazyValue)//第一次
    println(lazyValue)//第二次
    println("------------------")
    var testLazy = TestLazy()
    println(testLazy.lazyValue)//第一次
    println(testLazy.lazyValue)//第二次

    println("------------------")
    //那没问题了,使用TestLazy().lazyValue的写法,应该是每次都算第一次
    println("${TestLazy().hashCode()} || ${TestLazy().hashCode()}")
    //940060004 || 234698513
    //这种使用方法,每次都是一个新对象,hashcode值不一样
  • 下图是打印的详情


    图片.png

4 可观察属性 Observable

  • observable 可以用于实现观察者模式(看名字就知道和观察者模式的关系)
  • Delegates.observable() 函数接受两个参数: 第一个是初始化值, 第二个是属性值变化事件的响应器(handler)。
  • 在属性赋值后会执行事件的响应器(handler),它有三个参数:被赋值的属性、旧值和新值
  • 这个Delegates和 Delegate 类好像会用到的地方挺多
class ObservableUser {
    var info: String by Delegates.observable("初始化信息") { property, oldValue, newValue ->
        println("${property.name} 的 oldValue = $oldValue , newValue = $newValue")
    }
}
 //4-2 使用
    var observableUser  = ObservableUser()
    observableUser.info = "第一次赋值"
    observableUser.info = "第二次赋值"
  • 下图是打印的详情:


    图片.png

5 把属性储存在映射中

  • 个常见的用例是在一个映射(map)里存储属性的值。 这经常出现在像解析 JSON 或者做其他"动态"事情的应用中。 在这种情况下,你可以使用映射实例自身作为委托来实现委托属性
  • val属性用Map,var属性用MutableMap
  • 这么写确实会简洁很多,一个by就搞定了,还是很舒服的
class MapUser(val map: Map<String, Any>) {
    //Type 'Map<String, Any>' has no method 'setValue(MapUser, KProperty<*>, String)' and thus it cannot serve as a delegate for var (read-write property)
    //这里只能用val,要不然报红
    val name: String by map
    val url: String by map
}

//如果使用 var 属性,需要把 Map 换成 MutableMap
class MapUserVar(var map: MutableMap<String, String>) {
    var name: String by map
    var url: String by map
}
 //5-2 使用
    var mapUser = MapUser(
        mapOf(
            "name" to "垃圾菜鸟教程",
            "url" to "www.lajiRunoob.com"
        )
    )
    //emmm 本来想到了一个用法,在Adapter里面好像,但是Array并不能这么用
    println(mapUser.name)
    println(mapUser.url)
    println("---------------")
    //var的用法
    var mapUser2 = MapUserVar(
        mutableMapOf(
            "name" to "菜鸟教程真的rua圾",
            "url" to "www.ruajiRunoob.com"
        )
    )
    println(mapUser2.name)
    println(mapUser2.url)

6 Not Null

  • notNull 适用于那些无法在初始化阶段就确定属性值的场合
  • 还要再看看别人怎么用的,菜鸟教程真的,我哭死,太敷衍了。
//6-1 定义notNull属性
class TestNotNull {
    var notNull: String by Delegates.notNull<String>()
}

    //6-2 使用
    var notNull = TestNotNull()
    notNull.notNull = "real not null~"
    println(notNull.notNull)

7 局部委托属性

  • 看标题我懂了,就是局部属性也能委托嘛
  • 但是教程真的就一段不知道哪里copy的代码....我丢。
//你可以将局部变量声明为委托属性。 例如,你可以使一个局部变量惰性初始化
//这个示例代码真的无头无尾...菜鸟的编辑是累了么,眼看就最后几个了随便copy了一段代码?
fun partDelegation(computeFoo: () -> TestNotNull) {
    val memoizedFoo by lazy(computeFoo)
    val condition = true
    memoizedFoo.notNull = "不懂...."
    if (condition) {
        println(memoizedFoo.notNull)
    }
}

最后

菜鸟的教程就都看完了,其实最后还有一段,实在看不下去了,真的感觉看个基础的东西,以后再代码里或者项目里实践吧,菜鸟讲的东西,越往后面越不清楚。
接下来,从明天开始看android,那些使用Kotlin写的项目,或者知识。
加油~~

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容