代理关键字 by
属性代理:对象X代替属性a实现getter、setter方法。
接口代理:对象X代替类B实现接口C的方法。
举例
属性代理
在UI初始中使用过,代码如下:
1 class MainActivity : AppCompatActivity() { 2 3 private val mTvName: TextView by lazy { 4 findViewById(R.id.name) 5 } 6 7 override fun onCreate(savedInstanceState: Bundle?) { 8 super.onCreate(savedInstanceState) 9 setContentView(R.layout.activity_main) 10 } 11 }
接口lazy的实例代理了对象MainActivity实例的属性mTvName的getter方法。
lazy是一个Lambda函数,lazy实现:
1 /** 2 * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] 3 * and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED]. 4 * 5 * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access. 6 * 7 * Note that the returned instance uses itself to synchronize on. Do not synchronize from external code on 8 * the returned instance as it may cause accidental deadlock. Also this behavior can be changed in the future. 9 */ 10 public actual fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer) 11 12 /** 13 * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] 14 * and thread-safety [mode]. 15 * 16 * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access. 17 * 18 * Note that when the [LazyThreadSafetyMode.SYNCHRONIZED] mode is specified the returned instance uses itself 19 * to synchronize on. Do not synchronize from external code on the returned instance as it may cause accidental deadlock. 20 * Also this behavior can be changed in the future. 21 */ 22 public actual fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> = 23 when (mode) { 24 LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer) 25 LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer) 26 LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer) 27 } 28 29 /** 30 * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] 31 * and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED]. 32 * 33 * If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access. 34 * 35 * The returned instance uses the specified [lock] object to synchronize on. 36 * When the [lock] is not specified the instance uses itself to synchronize on, 37 * in this case do not synchronize from external code on the returned instance as it may cause accidental deadlock. 38 * Also this behavior can be changed in the future. 39 */ 40 public actual fun <T> lazy(lock: Any?, initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer, lock) 41 42 43 44 private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable { 45 private var initializer: (() -> T)? = initializer 46 @Volatile private var _value: Any? = UNINITIALIZED_VALUE 47 // final field is required to enable safe publication of constructed instance 48 private val lock = lock ?: this 49 50 override val value: T 51 get() { 52 val _v1 = _value 53 if (_v1 !== UNINITIALIZED_VALUE) { 54 @Suppress("UNCHECKED_CAST") 55 return _v1 as T 56 } 57 58 return synchronized(lock) { 59 val _v2 = _value 60 if (_v2 !== UNINITIALIZED_VALUE) { 61 @Suppress("UNCHECKED_CAST") (_v2 as T) 62 } else { 63 val typedValue = initializer!!() 64 _value = typedValue 65 initializer = null 66 typedValue 67 } 68 } 69 } 70 71 override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE 72 73 override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet." 74 75 private fun writeReplace(): Any = InitializedLazyImpl(value) 76 } 77 78 79 private class SafePublicationLazyImpl<out T>(initializer: () -> T) : Lazy<T>, Serializable { 80 @Volatile private var initializer: (() -> T)? = initializer 81 @Volatile private var _value: Any? = UNINITIALIZED_VALUE 82 // this final field is required to enable safe initialization of the constructed instance 83 private val final: Any = UNINITIALIZED_VALUE 84 85 override val value: T 86 get() { 87 val value = _value 88 if (value !== UNINITIALIZED_VALUE) { 89 @Suppress("UNCHECKED_CAST") 90 return value as T 91 } 92 93 val initializerValue = initializer 94 // if we see null in initializer here, it means that the value is already set by another thread 95 if (initializerValue != null) { 96 val newValue = initializerValue() 97 if (valueUpdater.compareAndSet(this, UNINITIALIZED_VALUE, newValue)) { 98 initializer = null 99 return newValue 100 } 101 } 102 @Suppress("UNCHECKED_CAST") 103 return _value as T 104 } 105 106 override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE 107 108 override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet." 109 110 private fun writeReplace(): Any = InitializedLazyImpl(value) 111 112 companion object { 113 private val valueUpdater = java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater( 114 SafePublicationLazyImpl::class.java, 115 Any::class.java, 116 "_value" 117 ) 118 } 119 }
当然能代理getter方法就能代理setter方法,上代码:
class Person() { private var mName: String by Delegates.observable("") { property, oldValue, newValue -> println("name setter old value: $oldValue to new value: $newValue") } }
源码实现:
1 /** 2 * Standard property delegates. 3 */ 4 public object Delegates { 5 /** 6 * Returns a property delegate for a read/write property with a non-`null` value that is initialized not during 7 * object construction time but at a later time. Trying to read the property before the initial value has been 8 * assigned results in an exception. 9 * 10 * @sample samples.properties.Delegates.notNullDelegate 11 */ 12 public fun <T : Any> notNull(): ReadWriteProperty<Any?, T> = NotNullVar() 13 14 /** 15 * Returns a property delegate for a read/write property that calls a specified callback function when changed. 16 * @param initialValue the initial value of the property. 17 * @param onChange the callback which is called after the change of the property is made. The value of the property 18 * has already been changed when this callback is invoked. 19 * 20 * @sample samples.properties.Delegates.observableDelegate 21 */ 22 public inline fun <T> observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit): 23 ReadWriteProperty<Any?, T> = 24 object : ObservableProperty<T>(initialValue) { 25 override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue) 26 } 27 28 /** 29 * Returns a property delegate for a read/write property that calls a specified callback function when changed, 30 * allowing the callback to veto the modification. 31 * @param initialValue the initial value of the property. 32 * @param onChange the callback which is called before a change to the property value is attempted. 33 * The value of the property hasn't been changed yet, when this callback is invoked. 34 * If the callback returns `true` the value of the property is being set to the new value, 35 * and if the callback returns `false` the new value is discarded and the property remains its old value. 36 * 37 * @sample samples.properties.Delegates.vetoableDelegate 38 * @sample samples.properties.Delegates.throwVetoableDelegate 39 */ 40 public inline fun <T> vetoable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Boolean): 41 ReadWriteProperty<Any?, T> = 42 object : ObservableProperty<T>(initialValue) { 43 override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = onChange(property, oldValue, newValue) 44 } 45 46 }
属性代理最重要的接口类源码:
1 /** 2 * Base interface that can be used for implementing property delegates of read-write properties. 3 * 4 * This is provided only for convenience; you don't have to extend this interface 5 * as long as your property delegate has methods with the same signatures. 6 * 7 * @param R the type of object which owns the delegated property. 8 * @param T the type of the property value. 9 */ 10 public interface ReadWriteProperty<in R, T> { 11 /** 12 * Returns the value of the property for the given object. 13 * @param thisRef the object for which the value is requested. 14 * @param property the metadata for the property. 15 * @return the property value. 16 */ 17 public operator fun getValue(thisRef: R, property: KProperty<*>): T 18 19 /** 20 * Sets the value of the property for the given object. 21 * @param thisRef the object for which the value is requested. 22 * @param property the metadata for the property. 23 * @param value the value to set. 24 */ 25 public operator fun setValue(thisRef: R, property: KProperty<*>, value: T) 26 }
其实,我们也可以实现类似接口,通过operator操作符:
1 class Foo() { 2 val x: Int by Person() 3 4 var y: Int by Person() 5 } 6 7 class Person() { 8 9 private var value: Int? = null 10 11 operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { 12 return value ?: throw IllegalStateException("Property ${property.name} should be initialized before get.") 13 } 14 15 operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { 16 this.value = value 17 } 18 19 }
接口代理
未使用代理 by :
1 interface IApi {
2 fun methodA()
3 fun methodB()
4 fun methodC()
5 }
6
7 class Person(private val api: IApi): IApi {
8
9 override fun methodA() {
10 api.methodA()
11 }
12
13 override fun methodB() {
14 api.methodB()
15 }
16
17 override fun methodC() {
18 api.methodC()
19 }
20
21 }
使用代理 by :
1 interface IApi {
2 fun methodA()
3 fun methodB()
4 fun methodC()
5 }
6
7 class Person(private val api: IApi) : IApi by api {
8 // 对象api代替类Person实现接口IApi方法
9 override fun methodC() {
10 TODO("Not yet implemented")
11 }
12 }