Kotlin委托

这篇具有很好参考价值的文章主要介绍了Kotlin委托。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

委托
委托 == 代理
方法内的成员永远拿不到thisRef:官方委托和自定义委托-》方法里面没办法使用反射
委托只能类委托和属性委托

Kotlin委托

本文链接:https://blog.csdn.net/feather_wch/article/details/132095759

类委托

1、类委托

  1. 委托的是接口的方法
// 只能用于接口
interface DB{
    fun save()
}
// 类CreateDBAction实现了接口DB,参数db是DB类型,类的实现委托给参数db。
// 目的:啥也不想干
class CreateDBAction(db: DB):DB by db

2、类委托的原理是什么?生成了什么代码?

  1. 成员变量:$$delegate_0 = 参数db
  2. 实现方法:委托给$$delegate_0调用save()
public final class CreateDBAction implements DB {
   // $FF: synthetic field
   private final DB $$delegate_0;

   public CreateDBAction(@NotNull DB db) {
      Intrinsics.checkNotNullParameter(db, "db");
      super();
      this.$$delegate_0 = db;
   }

   public void save() {
      this.$$delegate_0.save();
   }
}

3、类委托有什么用?

  1. 减少委托的代码
  2. Compose是重委托
CreateDBAction(SqlDB()).save()
CreateDBAction(OracleDB()).save()

属性委托

1、属性委托,委托的是 属性的 set和get

class MyKt{
    var value = 1314
    var number by ::value // 两个属性公用get和set
}
// number -> getNumber() -> getValue()
// number = 10 -> setNumber(10) -> setValue(10)

2、委托属性有什么用?

  1. 字段升级,老字段适配老用户,新字段用于新用户。共用一个get、set
class Database{
    var data = 941226 // 1.0
    var newData by ::data // 2.0
}

3、懒加载委托也就是属性委托

  1. 第一次获取时,才会获取,下面例子第一次获取耗时2秒,其他都立马获得
fun requestDownload(): String{
    Thread.sleep(2000L)
    return "sucess"
}

// 懒加载,
// 属性委托,委托给
val responseData : String by lazy {
    requestDownload()
}
// val responseData : String = SynchronizedLazyImpl(requestDownload())
// 借助了SynchronizedLazyImpl的get方法

fun main(){
    println("startloading...")
    println(responseData)
    println(responseData)
    println(responseData)
}

自定义属性委托

1、完全自己实现属性委托

// 自定义委托,定义好get和set之后,属性可以用该类实现属性委托
class Custom{
    operator fun getValue(owner: Owner, property: KProperty<*>) : String{
        return "AAA"
    }
    operator fun setValue(owner: Owner, property: KProperty<*>, value :String){

    }
}
class Owner{
    val responseData : String by Custom()
}

2、利用模板实现属性委托:ReadWriteProperty

// 自定义委托
class Custom2 : ReadWriteProperty<Owner, String>{
    var str = "default"
    override fun getValue(thisRef: Owner, property: KProperty<*>): String {
        return str
    }
    override fun setValue(thisRef: Owner, property: KProperty<*>, value: String) {
        str = value
    }
}

提供委托/暴露者委托

1、provideDelegate

  1. 额外的属性初始化逻辑:在属性被委托对象初始化之前进行一些额外的操作,例如数据验证、计算或日志记录等。
  2. 针对不同属性的不同行为:通过在不同的委托对象的provideDelegate方法中实现不同的逻辑,可以根据属性的不同需求,为每个属性提供不同的行为。
  3. 属性访问的可扩展性:可以为属性访问添加自定义的行为,例如缓存、延迟加载、权限控制等。
class Owner{
    val responseData : String by Custom()
}
// 自定义委托
class Custom(var str: String = "Default") : ReadWriteProperty<Owner, String>{
    override fun getValue(thisRef: Owner, property: KProperty<*>): String {
        return str
    }
    override fun setValue(thisRef: Owner, property: KProperty<*>, value: String) {
        str = value
    }
}
// provideDelegate,暴露者委托,== 选择器
class SmartDelegator{
    operator fun provideDelegate(thisRef:Owner, property: KProperty<*>):ReadWriteProperty<Owner, String>{
        return if(property.name.isEmpty()){
            Custom("empty")
        }else{
            Custom("normal")
        }
    }
}

实战场景

自己实现by lazy
class LazyInitDelegate<T> {
    private var initializer: (() -> T)? = null
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return initializer?.invoke() ?: throw IllegalStateException("Property not initialized")
    }
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: (() -> T)) {
        initializer = value
    }
}

class Example {
    val lazyProperty: String by LazyInitDelegate {
        // 在第一次访问属性时执行初始化逻辑
        println("Initializing lazy property")
        "Lazy Initialized"
    }
}

fun main() {
    val example = Example()
    println(example.lazyProperty) // 输出:Initializing lazy property \n Lazy Initialized
}

属性委托的日志记录
import kotlin.reflect.KMutableProperty
import kotlin.reflect.KProperty

class LoggingDelegate<T> {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        val value = property.getter.call()
        println("Property ${property.name} is accessed, value: $value")
        return value as T
    }
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        println("Property ${property.name} is set with value: $value")
        (property as KMutableProperty).setter.call(thisRef, value)
    }
}

class Example {
    var property: String by LoggingDelegate()
}

fun main() {
    val example = Example()
    example.property = "New value" // 输出:Property property is set with value: New value
    println(example.property) // 输出:Property property is accessed, value: New value \n New value
}

viewmodel

1、如何做到属性内部可以修改,外部不可以修改?

class Data{
    var data:String = ""
        private set

    private void changeData(value:String){
        data = value
    }
}
val data = Data()
data.data = "" // xxx 不可以
println(data.data) // 可以

2、如何做到kotlin的list集合,对内可以修改,对外界不可以修改

class MyKt{
    // 内部可以修改
    private val _data : MutableList<String> = mutableListOf()
    // 外部不可以修改
    val data : List<String> by :: _data
}

3、使用::用官方自定义委托,不使用需要自定义委托

4、用委托实现ViewModel的自动构造

class MyViewModel : ViewModel() {
    
}

fun main() {
    // 委托实现
    val mainViewModel : MyViewModel by viewModels()
}

private fun MainActivity.viewModels() : ReadOnlyProperty<MainActivity?, MyViewModel> =
    object : ReadOnlyProperty<MainActivity?, MyViewModel>{
        override fun getValue(thisRef: MainActivity?, property: KProperty<*>): MyViewModel {
            // thisRef永远为null
            return ViewModelProvider(this@viewModels).get(MyViewModel::class.java)
        }

    }
委托TextView:类似DataBinding
//  
operator fun TextView.provideDelegate(value: Any?, property: KProperty<*>) =
    object: ReadWriteProperty<Any?, String?>{
        override fun getValue(thisRef: Any?, property: KProperty<*>): String? {
            return text as String
        }

        override fun setValue(thisRef: Any?, property: KProperty<*>, value: String?) {
            text = value
        }

    }

// 创建TextView控件,双向绑定
var textView : TextView = findViewById(R.id.tv)
var message:String ? by textView

textView.text = "更改了控件的text -> message中的数值也会变"

message = "更改了数据 -> 更新UI"

双向绑定,多个控件操作数据

var data1 : String by textView1
var data2 : String by textView2
var data3 : String by textView3

data3 = data2
data2 = data1
data1 = "我在吃饭哦"
// 操作数据,View就会变,不用管UI刷新数据

出题目:如何手动实现String的代理(局部变量)?(用扩展函数)文章来源地址https://www.toymoban.com/news/detail-641328.html

var s1 = "wch"
var s2 : String by ::s1 // 类的成员变量才可以
var s3 : String by s1 // 不用官方的::

fun main() {
    var s1 = "wch"
    var s2:String by s1 // 报错
}
// Kotlin反射机制
operator fun String.setValue(item: Any?, property: KProperty<*>, value:String){
    // import kotlin.reflect.jvm.javaField, 已经被移除
    // property.javaField?.isAccessible = true
    // property.javaField?.set(item, value)
}
operator fun String.getValue(item: Any?, property: KProperty<*>) = this

到了这里,关于Kotlin委托的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Kotlin委托Delegate托管by

    property=\\\'user\\\' setValue - fly property=\\\'user\\\' getValue fly 0 - 2023 2023 - 2024 Delegates.observable追踪观察可变数据更新,Kotlin_zhangphil的博客-CSDN博客 **Java观察者模式的场景:一个女孩洗澡,被很多男孩偷看。女孩洞察后,搜索坏男孩,然后继续洗澡。*//*男孩Boy.java*/import java.util.Observable;不定长

    2024年02月09日
    浏览(35)
  • Kotlin笔记(五):泛型基础,委托

     Java自1.5版本引入了泛型的概念, Kotlin自然也支持泛型,Kotlin的泛型跟Java的泛型有相同之处,也有一些特别之处.  在一般的编程模式下,我们需要给任何一个变量指定一个具体的类型,而泛型允许我们在不指定具体类型的情况下进行编程,这样编写出来的代码将会拥有更好的

    2024年02月07日
    浏览(39)
  • Android(Kotlin) 委托(by) 封装 SharedPreferences

    在 Kotlin 中,委托是一种通过将自身的某个功能交给另一个对象来实现代码重用的技术。通过委托,我们可以将某个属性或方法的实现委托给另一个对象,从而减少重复代码的编写。委托可以用于实现多重继承、代码复用和扩展现有类的功能。 Kotlin 中的委托通过 “b

    2024年04月09日
    浏览(32)
  • kotlin基础--快速上手kotlin语言开发

    1.1 变量 var表示可变变量,val表示不可变变量,注意并不是常量。变量名写在前面,类型写在后面,编译器如果能推断出你的类型,那么类型是不用声明的 。 编译器自动推断类型。 空安全类型编译器报错 如果还是想给赋初始化值的话 注意:String和String?是两个完全不同的类

    2024年02月15日
    浏览(52)
  • Android开发:kotlin语言实现简易计算器

    输入两个数字,可选加减乘除操作符,并计算显示对应结果 随系统切换语言 可对结果进行四舍五入操作 界面布局:activity_main.xml文件代码 字符定义:string.xml文件代码 逻辑实现:MainActivity.kt 文件代码 方法一(偷懒): 复制文件到对应位置 方法二: 1. 绘制界面 2. 编写逻辑

    2023年04月08日
    浏览(46)
  • VS Code环境下配置Kotlin语言开发环境

    目录 一、安装VS Code扩展 1.安装Kotlin Language 2. 安装、配置Code Runner 二、安装Kotlin-compiler 1.下载Kotlin-compiler 2.安装JDK 3.配置环境变量 三、测试代码 安装成功后进入Code Runner扩展设置,下滑勾选Code-runner:Run In Terminal  打开Kotlin官网  Kotlin https://kotlinlang.org/  Get started打开Kotlin的官

    2024年02月09日
    浏览(51)
  • Android 安卓开发语言kotlin与Java该如何选择

            如今在Android开发中,应用层开发语言主要是Java和Kotlin,Kotlin是后来加入的,主导的语言还是Java。kotlin的加入仿佛让会kotlin语言的开发者更屌一些,其实不然。         有人说kotlin的引入是解决开发者复杂的逻辑,并且对空指针控制的比较友好,但是我们在开

    2024年02月11日
    浏览(61)
  • Kotlin 开发环境配置指南

    步骤 1:获取最新版 Kotlin 编译器 要配置 Kotlin 开发环境,首先需要从 JetBrains 官方 GitHub 仓库下载最新的 Kotlin 编译器。访问以下链接以获取最新版本的编译器: 在该页面中,找到适合您操作系统的 Kotlin 编译器发行版(例如 kotlin-compiler-xxxx.zip ),其中 xxxx 表示当前的版本号

    2024年01月25日
    浏览(41)
  • 使用Kotlin优化Java开发

    Kotlin是一种静态类型的编程语言,运行于Java虚拟机(JVM)、Android和WebAssembly。由JetBrains开发,其设计的主要目的是支持函数式编程和面向对象编程特性。Kotlin可以与Java互相调用,使得它对于现有Java生态系统中的开发人员来说非常有吸引力。与Java相比,它提供了更多的功能和语

    2024年02月09日
    浏览(42)
  • 【第三阶段】kotlin语言的内置函数takeif

    执行结果

    2024年02月11日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包