总结
啊,今天是菜鸟的最后一篇啊,说实话菜鸟的教程雀实有点拉跨。
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写的项目,或者知识。
加油~~

