Kotlin 代理属性

lazy() 是一个函数,它接受一个 lambda 并返回一个实例,Lazy<T> 该实例可以作为实现惰性属性的委托:第一次调用 get() 执行传递给的 lambdalazy() 并记住结果,随后的调用 get() 只返回记住的结果。

val lazyValue: String by lazy {
println(“computed!”)
“Hello”
}

fun main() {
println(lazyValue)
println(lazyValue)
}

默认情况下,惰性属性的评估是同步的:该值仅在一个线程中计算,所有线程将看到相同的值。如果不需要同步初始化委托,以便多个线程可以同时执行,则 LazyThreadSafetyMode.PUBLICATION 作为参数传递给 lazy() 函数。

如果您确定初始化将始终发生在与您使用该属性的线程相同的线程上,则可以使用 LazyThreadSafetyMode.NONE:它不会产生任何线程安全保证和相关开销。

lateinit 和 by lazy 的区别

我的理解是我们平时在项目中尽量少用 lateinit,因为很多东西我们是确定怎么初始化他的,这个时候只需要延迟初始化,使用 by lazy 就可以了。lateinit 我能想到的应用场景就是外部传了一个变量来初始化某个属性而且必不为空。由于 kotlinswift 一样,有着严格的检查,我们可以利用它来告诉编译器,我们要晚一点才能初始化它。这个也是在 swift 中不能优雅解决的一个点。

最近在看公司内部的项目,这个关键字被滥用了,看着贼难受。唉。。。

可观察属性

Delegates.observable() 接受两个参数:初始值和修改的闭包。 每次分配给属性时都会调用闭包(在执行分配之后)。它具有三个参数:被分配的属性、旧值和新值:

class User {
var name: String by Delegates.observable(“”) {
prop, old, new ->
println(“$old -> $new”)
}
}

fun main() {
val user = User()
user.name = “first”
user.name = “second”
}

如果您想拦截分配并否决它们,请使用 vetoable() 代替 observable()

委托给另一个属性

一个属性可以把他的 setter()getter() 代理给另一个属性。这种代理可以用于 top-levelclass 属性(成员或者扩展)。这种代理属性可以是:

  • 一个 top-level 属性
  • 同一个类中的成员属性或者扩展属性
  • 不同类中的成员属性或者扩展属性

像这种把一个属性委托给别一个属性的情况,要用 ::proper 的语法

var topLevelInt: Int = 0
class ClassWithDelegate(val anotherClassInt: Int)

class MyClass(var memberInt: Int, val anotherClassInstance: ClassWithDelegate) {
var delegatedToMember: Int by this::memberInt
var delegatedToTopLevel: Int by ::topLevelInt

val delegatedToAnotherClass: Int by anotherClassInstance::anotherClassInt
}
var MyClass.extDelegated: Int by ::topLevelInt

这个其实是很有用的。举个例子,如果我们想以向后兼容的方式重命名属性时:引入一个新的属性,用注释对旧属性进行 @Deprecated 注释,然后委托其实现。

class MyClass {
var newName: Int = 0
@Deprecated(“Use ‘newName’ instead”, ReplaceWith(“newName”))
var oldName: Int by this::newName
}
fun main() {
val myClass = MyClass()
// Notification: ‘oldName: Int’ is deprecated.
// Use ‘newName’ instead
myClass.oldName = 42
println(myClass.newName) // 42
}

上述两个例子是官方文档(1.5.10)提供的用法,老版本的 kotlin 是不支持的

属性代理

对于只读属性 val,委托应提供 getValue() 具有以下参数的运算符函数:

thisRef 必须是属性所有者的相同或超类型(对于扩展属性,它应该是被扩展的类型)。

property 必须是类型 KProperty<*> 或其超类型。

getValue() 必须返回与属性(或其子类型)相同的类型。

class Owner {
val valResource: Resource by ResourceDelegate()
}

class ResourceDelegate {
operator fun getValue(thisRef: Owner, property: KProperty<*>): Resource {
return Resource()
}
}

对于可变属性 var,委托必须额外提供 setValue() 具有以下参数的运算符函数:

thisRef 必须是属性所有者的相同或超类型(对于扩展属性,它应该是被扩展的类型)。

property 必须是类型 KProperty<*> 或其超类型。

value 必须与属性(或其超类型)具有相同的类型。

getValue()/setValue() 函数可以作为委托类的成员函数或扩展函数提供。当您需要将属性委托给最初不提供这些功能的对象时,后者很方便。这两个函数都需要用 operator 关键字标记。

您可以将委托创建为匿名对象,而无需使用接口 ReadOnlyPropertyReadWritePropertyKotlin 标准库创建新类。它们提供了所需的方法:getValue()ReadOnlyProperty 中声明,ReadWriteProperty 扩展它并添加 setValue()。因此,您可以在需要传递 ReadOnlyProperty 的时候传递 ReadWriteProperty

fun resourceDelegate(): ReadWriteProperty<Any?, Int> =
object : ReadWriteProperty<Any?, Int> {
var curValue = 0
override fun getValue(thisRef: Any?, property: KProperty<>): Int = curValue
override fun setValue(thisRef: Any?, property: KProperty<
>, value: Int) {
curValue = value
}
}

val readOnly: Int by resourceDelegate() // ReadWriteProperty as val
var readWrite: Int by resourceDelegate()

转换规则

Kotlin 编译器为每个委托属性生成一个辅助属性并委托给它。例如,为属性生成 prop 隐藏属性prop$delegate,访问器的代码简单地委托给这个附加属性:

class C {
var prop: Type by MyDelegate()
}

// this code is generated by the compiler instead:
class C {
private val prop d e l e g a t e = M y D e l e g a t e ( ) v a r p r o p : T y p e g e t ( ) = p r o p delegate = MyDelegate() var prop: Type get() = prop delegate=MyDelegate()varprop:Typeget()=propdelegate.getValue(this, this::prop)
set(value: Type) = prop$delegate.setValue(this, this::prop, value)
}

Kotlin 编译器 prop 在参数中提供了所有必要的信息:第一个参数 this 引用外部类的实例,C并且this::propKProperty 描述 prop 自身的类型的反射对象。

类代理

interface Base {
val message: String
fun print()
}

class BaseImpl(val x: Int) : Base {
override val message = “BaseImpl: x = $x”
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水!

为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!

Android架构师之路很漫长,一起共勉吧!

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

高级、架构师对你更是如鱼得水!

为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!

Android架构师之路很漫长,一起共勉吧!

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
  • 9
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值