委托
简单委托
如果把接口
或抽象类
理解为是方法抽象层面
的一致性
,委托
则可以认为是解决了方法实现层面
的一致性
。更直接的,它本质上是允许我们在实现层面
上进行复用。
本应由c属性
实现的方法的委托给已经实现接口的a属性
与b属性
interface A {
fun a()
}interface B {
fun b()
}var a = object : A {
override fun a() {
println("a function delegated by${this}")
}
}
var b = object : B {
override fun b() {
println("b function delegated by${this}")
}
}fun main(args: Array) {var c = object : A by a, B by b{ }
c.a() //打印 "a function delegated bydoulala.kotlin.demo.delegation.DelegationKt$a"
c.b() //打印 "b function delegated bydoulala.kotlin.demo.delegation.DelegationKt$b"
}
实验1:如果只想委托部分方法,关键方法自己实现。
var d = object : all {
override fun a() {
//donothing
println("d.a function do nothing")
}override fun b() {
println("d.b function delegated by${this}")
}
}fun main(args: Array) {var c = object : all by d {
override fun a() {//override d实例的 a()方法
println("c.a function override d.a function")
}
}
c.b()//委托给d.b(), 输出"d.b function delegated bydoulala.kotlin.demo.delegation.DelegationKt$d"
c.a()//最终将调用 c.a()方法,输出"c.a function override d.a function"
}
实验2,如果同时继承多个接口,接口方法名一样,会先调用哪个? 会报错
interface A {
fun a()
fun samename()
}interface B {
fun b()
fun samename()
}var a = object : A {
override fun samename() {
println("samename function in a")
}override fun a() {
println("a function ")
}
}
var b = object : B {
override fun samename() {
println("samename function in b")
}override fun b() {
println("b function ")
}
}fun main(args: Array) {var c = object : A by a, B by b{} //会报错,被提示实现了多次
c.a()
c.b()
c.samename()}
-
委托(Delegation)
的关键词是by
-
委托
可以通过重写方法
控制委托
的范围 -
委托
时会严格校验被委托的方法
来源,如果出现了相同的方法,会报错(这里与继承的判断是有区别的) 。限制就是安全所在。
【委托】系统为我们提供了一些常用的属性委托,包括:
-
延迟属性(lazy properties)
: 其值只在首次访问时计算; -
可观察属性(observable properties)
: 监听器会收到有关此属性变更的通知; - 把多个属性储存在一个
映射map
中,而不是每个存在单独的字段中。
- lazy属性主要提供了
只读属性
——通过计算后设置属性值
的能力
- 他提供了三种模式处理线程安全,包括 -
- 用于多线程间需要同步的
LazyThreadSafetyMode.SYNCHRONIZED
- 如存在多线程使用,但是无需同步的
LazyThreadSafetyMode.PUBLICATION
- - 单线程场景的的
LazyThreadSafetyMode.NONE
fun main(args: Array) {
val p: String by lazy(LazyThreadSafetyMode.NONE) {
println("get() progress")
"value"//lazy其实是重写了get()方法,最后一行是p的值
}
}
我们看一下他的源码,发现Lazy的核心就是重写属性的get()方法:
public fun lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy =
when (mode) {
LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)
LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)
LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)
}//最简单的是UnsafeLazyImpl,单线程模式
internal class UnsafeLazyImpl(initializer: () -> T) : Lazy, Serializable {
private var initializer: (() -> T)? = initializer//拿到初始化的lambda方法
private var _value: Any? = UNINITIALIZED_VALUE //定义了一个非法值override val value: T
get() {//这行应该和上面一行连起来看,就是重写该属性的get()方法
if (_value =https://www.it610.com/article/== UNINITIALIZED_VALUE) {
_value = initializer!!() //初始化
initializer = null
}
@Suppress("UNCHECKED_CAST")
return _value as T //返回初始化后的值
}override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE // 这个是Lazy的方法,用于记录是否初始化结束。override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."//重写toString方法private fun writeReplace(): Any = InitializedLazyImpl(value) //未找到方法作用
}
可观察属性 Observable
Delegates
一共提供两个代理工厂observable
与vetoable
方法observable
委托对象可以对数值的变化
进行监控
。共需要提供两个参数- 参数A:
initialValue: T
用于设置初始值 - 参数B:
(property: KProperty<*>, oldValue: T, newValue: T) -> Unit
监控并获取对象引用
、变更前数据
与变更后数据
var name: String by Delegates.observable("init") { prop, old, new ->
println("old : $old")
println("new : $new")
}fun main(args: Array) {
name = "123"
name = "456"
}
vetoable
委托对象可以对数值的变化
进行控制
。与observable
唯一的不同是,参数B的返回值变为了Boolean,如果返回值为true
则接受
变化,如果为false
则不接受
变化。var age: Int by Delegates.vetoable(18) { prop, old, new ->
println("old : $old")
println("new : $new")
val accept=new>16
println("accept : $accept")
accept //只接受>16的变更
}fun main(args: Array) {
age = 12
println("age =$age") //输出: "age =18"
age = 20
println("age =$age")//输出: "age =20"
}
解密属性委托
属性委托的原理是
by
了一个对象,这个对象其实是委托了getValue
与 setValue
方法:
interface ReadOnlyProperty {//只读的Delegate
operator fun getValue(thisRef: R, property: KProperty<*>): T
}interface ReadWriteProperty {//读写的Delegate
operator fun getValue(thisRef: R, property: KProperty<*>): T
operator fun setValue(thisRef: R, property: KProperty<*>, value: T)
}
一个自定义的属性委托:
fun main(args: Array) {var a: String by object : ReadWriteProperty {
var _value: String = "" //属性委托一般都需要一个间接对象进行数据读取与赋值override fun getValue(thisRef: Any?, property: KProperty<*>): String {print("in getValue")
print("$thisRef")
print("$property")
return _value
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {println("in setValue")
_value = https://www.it610.com/article/value
}
}
a="1213"//输出 “in setValue”
println(a) //输出 in getValue null var a: kotlin.String1213}
推荐阅读
- 科学养胃,别被忽悠,其实真的很简单
- opencv|opencv C++模板匹配的简单实现
- 松软可口易消化,无需烤箱超简单,新手麻麻也能轻松成功~
- 简单心理2019春A期+32+张荣
- 《算法》-图[有向图]
- android防止连续点击的简单实现(kotlin)
- 机器学习一些简单笔记
- Android超简单实现沉浸式状态栏
- v-charts简单使用
- 校园非自愿来访者辅导问句学习