博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Kotlin基础 — 委托
阅读量:6938 次
发布时间:2019-06-27

本文共 6321 字,大约阅读时间需要 21 分钟。

目录

  1. 类委托
  2. 属性委托 2.1. 方法一:可以按需继承 ReadOnlyProperty、ReadWriteProperty 两个接口中的一个; 2.2. 方法二:自己定义,但方法参数必须和 1 中接口的方法参数一致;
  3. 标准委托 3.1. 延迟属性 Lazy 3.2. 可观察属性 Observable 3.3. 把属性储存在映射中
  4. 使用场景

类委托(代理模式)

类的两种代理方法

interface Base {    fun print()}class BaseImpl(val x: Int) : Base {    override fun print() { print(x) }}// 第一种:这里直接使用关键字 by 进行代理class Derived(base: Base) : Base by base// 第二种:class Derived(base: Base) : Base {    val base : Base    init {        this.base = base    }    override fun print() {        base.print() // base是BaseImpl的实例对象    }}// 测试class Main {	fun main() {	    val b = BaseImpl(10)	    Derived(b).print() // prints 10	}}复制代码

属性委托

语法结构: val/var <property name>: <Type> by <expression>

两种实现方法:

  1. 方法一:可以按需继承 ReadOnlyProperty、ReadWriteProperty 两个接口中的一个;

    // 读取属性public interface ReadOnlyProperty
    { public operator fun getValue(thisRef: R, property: KProperty<*>): T}// 读写属性public interface ReadWriteProperty
    { // 关键字 operator 重载操作符 public operator fun getValue(thisRef: R, property: KProperty<*>): T public operator fun setValue(thisRef: R, property: KProperty<*>, value: T)}复制代码

    示例代码:

    class Delegate
    : ReadWriteProperty
    { // 重写了getValue()方法 override fun getValue(thisRef: Any?, property: KProperty<*>): T { return ... } override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { } }class Main { var p: String by Delegate
    () fun test() { val main = Main() print(main.p) // 会调用到Delegate中的getValue()方法 main.p = "Elson" // 会调用到Delegate中的setValue()方法 }}复制代码
  2. 方法二:自己定义,但方法参数必须和 1 中接口的方法参数一致;

    class Delegate
    { // 使用关键字 operator 来实现重载 operator fun getValue(thisRef: Any?, property: KProperty<*>): T { return "$thisRef, thank you for delegating '${property.name}' to me!" } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { println("$value has been assigned to '${property.name}' in $thisRef.") }}复制代码

    示例代码:

    class Main {	var p: String by Delegate
    () //属性 p 被代理 fun test() { val main = Main() print(main.p) // 会调用到Delegate中的getValue()方法 main.p = "Elson" // 会调用到Delegate中的setValue()方法 }}复制代码

标准委托

1. 延迟属性 Lazy

  1. 示例代码:

    val lazyValue: String by lazy {    println("computed!")    "Hello"}fun main(args: Array
    ) { println(lazyValue) //第一次调用lazyValue时,会先初始化lazy{}作用区间的代码,即打印一个"computed!",然后返回一个"Hello"字符串并赋值给lazyValue; println(lazyValue) //第二次调用lazyValue时,直接将"Hello"赋值给lazyValue;可参考下面的源码}复制代码
  2. 源码:Lazy.kt 文件

    public fun 
    lazy(initializer: () -> T): Lazy
    = SynchronizedLazyImpl(initializer)private object UNINITIALIZED_VALUE@JvmVersionprivate class SynchronizedLazyImpl
    (initializer: () -> T, lock: Any? = null) : Lazy
    , Serializable { private var initializer: (() -> T)? = initializer @Volatile private var _value: Any? = UNINITIALIZED_VALUE // final field is required to enable safe publication of constructed instance private val lock = lock ?: this override val value: T get() { val _v1 = _value if (_v1 !== UNINITIALIZED_VALUE) { @Suppress("UNCHECKED_CAST") return _v1 as T //第二次执行操作时,这里直接返回对象 } return synchronized(lock) { val _v2 = _value if (_v2 !== UNINITIALIZED_VALUE) { @Suppress("UNCHECKED_CAST") (_v2 as T) } else { val typedValue = initializer!!()//第一次使用时执行这里,将lazy大括号内的代码进行初始化,并返回最后一行的数据并赋值给typedValue _value = typedValue initializer = null typedValue } } } override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet." private fun writeReplace(): Any = InitializedLazyImpl(value)}复制代码

2. 可观察属性 Observable

示例代码:

class User {	// 方法一:    var name: String by Delegates.observable("
") { prop, old, new -> println("$old -> $new") } // 方法二:Delegates.observable()实际上就是对ObservableProperty的一层封装 var name : String by object : ObservableProperty
("
") { override fun afterChange(property: KProperty<*>, oldValue: String, newValue: String) { println("$oldValue -> $newValue") } }}fun main() { val user = User() user.name = "first" user.name = "second"}复制代码

输出结果 < no name > -> first first -> second

源码:

public inline fun 
observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit): ReadWriteProperty
= object : ObservableProperty
(initialValue) { override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue)}public inline fun
vetoable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Boolean): ReadWriteProperty
= object : ObservableProperty
(initialValue) { // 需要返回一个boolean值,判断是否需要发射,默认为true override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = onChange(property, oldValue, newValue)}public abstract class ObservableProperty
(initialValue: T) : ReadWriteProperty
{ private var value = initialValue protected open fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = true protected open fun afterChange (property: KProperty<*>, oldValue: T, newValue: T): Unit {} // 代理后,自动被调用 public override fun getValue(thisRef: Any?, property: KProperty<*>): T { return value } // 代理后,自动被调用 public override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { val oldValue = this.value // 判断是否需要发射,默认为true if (!beforeChange(property, oldValue, value)) { return } this.value = value afterChange(property, oldValue, value) }}复制代码

3. 把属性储存在映射中

这部分不知道怎么看源码

class User(val map: Map
) { val name: String by map val age: Int by map}val user = User(mapOf( "name" to "John Doe", "age" to 25))复制代码

转载地址:http://swsnl.baihongyu.com/

你可能感兴趣的文章
我为NET狂官方面试题-数据库篇
查看>>
俯瞰java内存模型和线程上下文切换
查看>>
HTML基本元素(四)
查看>>
Android -- 仿淘宝广告条滚动
查看>>
七大查找算法
查看>>
Google Search Operators
查看>>
sqlPlus使用
查看>>
python - unittest - 单元测试
查看>>
React文档(四)渲染元素
查看>>
问题清单
查看>>
安装msdn
查看>>
CSS中使用display:none的注意事项
查看>>
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
查看>>
第一篇:多线程使用
查看>>
JAVA集合类汇总
查看>>
我的Android进阶之旅------> Android在TextView中显示图片方法
查看>>
调整CodeIgniter错误报告级别
查看>>
文件的内容操作
查看>>
Css基础2
查看>>
知识一些备忘
查看>>