val test = PropertyClass()
test.name = “7890”
println(test.name)
}
属性委托有四种情况在实际开发中比较常用:
延迟属性。
非空属性。
可观测属性。
map 委托。
延迟属性: 属性只有在第一次访问时才会计算,之后则会将之前的计算结果缓存起来供后续调用。如下是一个案例:
//延迟属性:依赖 kotlin 提供的 lazy 函数实现,函数参数是一个 lambada 表达式
//源码 LazyJVM.kt 中 public actual fun lazy(initializer: () -> T): Lazy = SynchronizedLazyImpl(initializer) 方法
val lazyValue: Int by lazy {
println(“lazyValue lazy”)
28
}
fun testRun() {
//首次调用时触发计算
println(lazyValue)
//可以看到后续调用是直接用了上次的缓存结果
println(lazyValue)
}
非空属性: 适用于那些无法在初始化阶段确认属性值的场合。lateinit 修饰符只能在类(不在主构造函数中)内声明的var 属性上使用,而且只有在该属性没有自定义集合或者设置器时,此外属性的类型必须是非空的,并且不能是基元类型。而非空属性没有这些限制。其他他们的作用是相同的。如下是一个案例:
//【工匠若水 加微信 yanbo373131686 联系我,关注微信公众号:码农每日一题 未经允许严禁转载 https://blog.csdn.net/yanbober】
class Tree {
//非空属性解决了 var name: String? = null 导致后续判断冗余
//非空属性解决了 var name: String = “” 初值隐晦问题
//非空属性解决了 lateinit 的一些缺陷,譬如 lateinit 只能应用于非基元类型,譬如不能用于 Int 等问题
var name: String by Delegates.notNull()
}
fun testRun() {
val tree = Tree()
//运行时异常,没有赋值而使用 IllegalStateException: Property name should be initialized before get.
//println(tree.name)
tree.name = “123”
println(tree.name)
}
可观测属性: kotlin 提供了 observable 赋值后观测器和 vetoable 赋值前拦截观测器的能力。如下是一个案例:
class Tree {
//可观测属性初值,10 是属性初值,当属性被赋值后会触发回调 lambada 表达式
var age: Int by Delegates.observable(10) {
property, oldValue, newValue ->
println(“property name is ${property.name}, old value is $oldValue, new value is $newValue”)
}
//可观测属性初值,10 是属性初值,当属性被赋值前会触发回调 lambada 表达式,可以做到类似属性值赋值拦截器的效果
//这里当赋值小于等于0则丢弃
var defaultCount: Int by Delegates.vetoable(10) {
property, oldValue, newValue -> when {
newValue <= 0 -> {
println(“unsupport value of $newValue, refused!”)
return@vetoable false
}
else -> {
println(“property name is ${property.name}, old value is $oldValue, new value is $newValue”)
return@vetoable true
}
}
}
}
fun testRun() {
val tree = Tree()
tree.age = 10
tree.age = 11
tree.age = 12
println(tree.age)
println("-------------")
tree.defaultCount = 100
tree.defaultCount = -2
tree.defaultCount = 101
println(tree.defaultCount)
}
map 委托: 可以将属性值存储到 map 当中。通常出现在 json 解析或者一些动态行为,在这种情况中可以将 map 实例作为类中属性的委托。注意:map 中的 key 名字必须要和属性的名字一致才行,否则委托后运行解析时会抛出 NoSuchElementException 异常提示 key name 不存在。下面是只读 map 属性委托的案例:
class Result (map: Map
val name: String by map
val address: String by map
val age: Int by map
val date: Date by map
override fun toString(): String {
return "{name: ${this.name}, address: ${this.address}, " +
“age: ${this.age}, date: ${this.date}}”
}
}
fun testRun() {
val result = Result(mapOf(
“name” to “ruoshui”,
“address” to “zhuhai”,
“age” to 18,
“date” to Date()
))
println(result.toString())
}
下面是读写 map 属性委托的案例(可以看到背后都是交给 map 存储的,写属性后 map 会跟着变化):
//【工匠若水 加微信 yanbo373131686 联系我,关注微信公众号:码农每日一题 未经允许严禁转载 https://blog.csdn.net/yanbober】
class Result (map: MutableMap
var name: String by map
var address: String by map
var age: Int by map
var date: Date by map
override fun toString(): String {
return "{name: ${this.name}, address: ${this.address}, " +
“age: ${this.age}, date: ${this.date}}”
}
}
fun testRun() {
val map: MutableMap
“name” to “ruoshui”,
“address” to “zhuhai”,
“age” to 18,
“date” to Date()
)
val result = Result(map)
println(result.toString())
println(map[“name”])
println("--------")
result.name = “gongjiang”
println(result.toString())
println(map[“name”])
}
对于每个委托属性来说,kotlin 编译器在底层会生成一个辅助的属性,然后将原有属性的访问委托给这个辅助属性。比如说,对于属性 prop 来说,kotlin 编译器所生成的隐含属性为prop$delete,然后对原有的 prop 属性的访问器的访问都只是委托给了这个额外的辅助属性。
提供委托(providing a delegate)
通过定义 provideDelegate operator,我们可以扩展委托的创建过程逻辑。如果对象定义了 provideDelegate 方法,那么该方法就会被调用来创建属性的委托实例。下面是一个案例:
//委托实现类
总结算法知识点繁多,企业考察的题目千变万化,面对越来越近的“金九银十”,我给大家准备好了一套比较完善的学习方法,希望能帮助大家在有限的时间里尽可能系统快速的恶补算法,通过高效的学习来提高大家面试中算法模块的通过率。
这一套学习资料既有文字档也有视频,里面不仅仅有关键知识点的整理,还有案例的算法相关部分的讲解,可以帮助大家更好更全面的进行学习,二者搭配起来学习效果会更好。
部分资料展示:
有了这套学习资料,坚持刷题一周,你就会发现自己的算法知识体系有明显的完善,离大厂Offer的距离更加近。
资料获取方法:点赞+关注+转发,然后进入我的【GitHub】,里面有免费获取途径
3959265050)]
[外链图片转存中…(img-VquqzoHt-1643959265050)]
[外链图片转存中…(img-e03ctbyz-1643959265051)]
有了这套学习资料,坚持刷题一周,你就会发现自己的算法知识体系有明显的完善,离大厂Offer的距离更加近。
资料获取方法:点赞+关注+转发,然后进入我的【GitHub】,里面有免费获取途径



