美文网首页
Kotlin的委托属性

Kotlin的委托属性

作者: 132xin | 来源:发表于2020-11-12 18:46 被阅读0次

委托属性的语法

val/var <属性名>:<类型> by <表达式>
在by后面的表达式是改委托,因为属性对应的get()(与set())会被委托给它的getValue()与setValue()方法。属性的委托不必实现任何接口,但需要提供一个getValue()函数(var属性还需要提供setValue()函数)
例如:

fun main(){
    val e=Example()
    println(e.d)
    e.d=6

}
class Example{
    var d:Int by DelegateTest()
}
class DelegateTest{
    operator fun getValue(thisRef:Any?,property:KProperty<*>):Int{
        return 1
    }
    operator fun setValue(thisRef: Any?,property: KProperty<*>,value:Int){
        println("$value has been assigned to '${property.name}' in $thisRef.")
    }

}

输出的结果:

1
6 has been assigned to 'd' in com.hx.learn.Example@433c675d.

从输出的结果可以知道,当我们从读取实例的d的值的时候,会调用委托类的getValue()函数,当我们给实例的d赋值的时候,会调用setValue()函数。
从上面委托类的两个函数中看到都包含了thisRefproperty两个参数的,第一个参数是读出d的对象,第二个参数保存了对d自身的描述。

属性委托的要求

  • 对于一个只读属性(即val声明的),委托必须提供一个操作函数getValue(),getValue()的函数的返回值必须与属性相同类型(或者是其值类型),并且函数具有以下参数
  • thisRef必须与属性所有者类型相同或者是其超类。
  • property必须是类型KProperty<*>或者是其超类。
  • 对于一个可变属性(即var声明的),委托必须额外提供一个操作函数setValue(),该函数具有以下参数:
  • thisRef必须与属性所有者类型相同或者是其超类。
  • property必须是类型KProperty<*>或者是其超类。
  • value必须与属性类型相同(或者是其超类)

标准委托

Kotlin标准库为几种有用的委托提供了工厂方法:

延迟属性Lazy

lazy()是接受一个lambda并返回一个Lazy<T>实例的函数,返回的实例可以延迟属性的委托:第一次调用get()会执行已传递给lazy()的lamdba表达达式并记录结果,后续调用get()只返回记录的结果。

fun main(){
    val lazyValue:String by lazy{
        println("你好")
        "lazy"
    }
    println(lazyValue)
    println("-----------")
    println(lazyValue)
}
image.png
在默认的情况下,对于lazy属性的求值是同步锁的:该值只在前一个线程中计算,并且所有线程看到相同的值。如果初始化委托的同步锁不是必需的,这样多个线程可以同时执行,那么将LazyThreadSafetyMode.PUBLICATION作为参数传递给lazy()函数。而如果你确定初始化将总是发生在与属性使用位于相同的线程,那么可以使用LazyThreadSafetyMode.NONE作为Lazy()函数的参数,它不会有任何线程安全的保证以及 相关的开销。
可观察属性Observable

Delegates.observable()接受两个参数:初始化与修改时处理程序。每当我们给属性赋值时会调用该处理程序(在赋值后执行)。它有是三个参数:被赋值的属性,旧值与新值。
例如:

fun main(){
    var person=Person()
    person.age=15
    person.age=16

}
class Person{
    var age:Int by Delegates.observable(10){
        property, oldValue, newValue ->
          println("${property.name}:{$oldValue}->{$newValue}")
       
    }
}

结果:

age:{10}->{15}
age:{15}->{16}

observable()是在赋值之后调用处理程序的,如果想在属性被赋新值生效前会调用处理程序可以使用vetoable()。
voteable的处理程序中返回的是布尔值,如果返回为ture则让赋值生效,否则赋值不生效。

委托给另一个属性

从kotlin 1.4开始,一个属性可以帮它的getter与setter委托给另一个属性。该委托属性可以是:

  • 顶层属性
  • 同一个类的成员或扩展属性
  • 另一个类的成员或扩展属性

将一个属性委托给另一个属性,应在委托名称中使用::限定符。当想要以一种向后兼容的方式命名一个属性性时,使用@Deprecated注解来注解旧的属性,并委托其实现。

class MyClass {
   var newName: Int = 0
   @Deprecated("Use 'newName' instead", ReplaceWith("newName"))
   var oldName: Int by this::newName
}

fun main() {
   val myClass = MyClass()
   myClass.oldName = 42
   println(myClass.newName) // 输出42
}
将属性储存在映射中

常见的用例就是在一个映射(map)里面存储的值,可以使用映射实例自身作为委托来实现委托属性。
例如:

fun main(){
    var person=Person(
            mapOf("name" to "Kotlin"
                    ,"age" to 10)
    )
}
class Person(map:Map<String,Any?>){ 
    val age:Int by map 
    val name:String by map
}

委托属性会从这个映射中取值(通过字符串键——属性的名称)

 println(person.age)
 println(person.name)

 输出:
 10
 Kotlin

如果是var属性的,需要将只读的Map换成MutableMap。

局部委托属性
fun main(){
   example(2)
}
fun example(value:Int){
    val tempInt by lazy {
        println("第一次被调用")
        value
    }
    println(tempInt)
    println(tempInt)

}

结果:

第一次被调用
2
2

tempInt变量只有在第一才访问时,才会执行处理程序,之后访问就不再执行。

相关文章

  • 玩转 Kotlin 委托属性

    Kotlin 属性 要讲 Kotlin 的委托属性,要先从 Kotlin 的属性说起,当然关于属性的定义就不多介绍...

  • Kotlin-委托,是否被低估了?

    1、属性委托 kotlin中的委托主要分为类的委托和属性的委托,我们先重点来看属性委托,用的比较多。 标准委托 k...

  • Kotlin委托

    Kotlin委托 1.Kotlin中的委托有两种形式,一种是委托模式,一种是委托属性。 2.委托模式是设计模式中的...

  • Kotlin的委托属性

    委托属性的语法 val/var <属性名>:<类型> by <表达式>在by后面的表达式是改委托,因为属性对应的g...

  • 20.Kotlin属性委托

    Kotlin属性委托(delegated property) 示例代码 输出 语法是: val/var <属性名>...

  • Kotlin-map属性委托

    Kotlin-map属性委托 委托属性在实际开发中是有如下4种使用情况的 1、延迟属性。 2、可观测属性。 3、非...

  • Kotlin Weekly 中文周报 —— 14

    Kotlin 开发中文周报 文章 对比 Java,Kotlin 中我最喜欢的功能 Kotlin 自定义委托属性(C...

  • Kotlin-属性委托深入详解

    Kotlin-属性委托深入详解 学习一下属性的委托(delegated property),我们知道定义一个类的属...

  • Kotlin-可观测属性委托(Observable)-Deleg

    Kotlin-可观测属性委托(Observable)-Delegates.observable Delegates...

  • kotlin语法糖以及原理

    kotlin by关键字实现委托属性与委托类 委托类 需要注意的是: CountingSet3 必须实现一个接口,...

网友评论

      本文标题:Kotlin的委托属性

      本文链接:https://www.haomeiwen.com/subject/nxiubktx.html