委托 by 操作符

news2024/9/25 13:22:22

属性委托给属性

使用 by:: 操作符,代表调用系统内置的方法。

读:getVaule

写:setValue

共享同一个数据。

/**
 * 属性委托给属性
 * by:: 系统内置的方法,非自定义的
 * 共享同一个数据
 */
var num:Float = 9999.0f

/**
 * newNum属性委托使用num属性的set和get
 * by:: 系统内置的方法,非自定义的
 */
var newNum :Float by:: num

fun main(args: Array<String>) {
    println("改变newNum的值,num的值也会改变")
    newNum = 0.5f
    println(newNum)
    println(num)

    println("改变num的值,newum的值也会改变")
    num = 1.5f
    println(newNum)
    println(num)
}

属性委托给类

继承委托(将继承接口的实现委托给构造函数的参数)

可以在实例化时由传入的参数决定使用哪个类实现接口。

package agency

/**
 * 属性委托给类
 * 第一种:继承时将接口的实现委托给构造函数的参数
 */
interface DB{
    fun open();
}

class MyDB:DB{
   override fun open(){
       print("我是MyDB")
   }
}

class SqlDB:DB{
    override fun open(){
        print("我是SqlDB")
    }
}

/**
 * CreateDB类将DB接口的实现委托给了构造函数中的参数db来实现。
 */
class CreateDB(db:DB):DB by db{

}

fun main(args: Array<String>) {
    //具体使用,在创建的时候传入参数。
    var db = MyDB()
    var createDB = CreateDB(db)
    createDB.open()
}

自定义委托类

自定义委托类有两种方法,一种是自行实现getValue和setValue方法,一种是通过实现ReadWriteProperty/ReadOnlyProperty接口。

两者原理一致。

属性通过by操作符委托给类。

在读属性的时候访问委托类的getValue函数,在写属性的时候访问委托类的setValue函数。

package agency

import kotlin.properties.ReadOnlyProperty
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

/**
 * 属性委托给类
 * 第二种:自定义委托类
 */
class TestAgency{
    /**
     * 将str的数据委托给CustomAgency类的实例
     * var 可读可写 被委托类需要实现setVaule和getVaule
     */
    var str:String by CustomAgencyString()

    var str02:String by CustomAgencyString02()

    /**
     * 将finalNum的数据委托给CustomInt类的实例
     * val 可读不可写 被委托类需要只实现getVaule即可
     */
    val finalNum:Int by CustomAgencyInt()

    val finalNum02:Int by CustomAgencyInt02()
}

/**
 * 第一种:自定义委托类,自己实现getValue和setValue方法
 */
class CustomAgencyString{
    var strData:String = "我是CustomAgency"

    /**
     * 自定义委托实现
     * 第一个参数是委托属性所在的类 TestAgency
     * 第二个参数是 KProperty<*> 固定
     * 返回值类型是委托属性的类型
     */
    operator fun getValue(any: Any, property: KProperty<*>): String {
        return strData
    }

    /**
     * 自定义委托实现
     * 第一个参数是委托属性所在的类 TestAgency
     * 第二个参数是 KProperty<*> 固定
     * 第三个参数是 要设置的数据
     */
    operator fun setValue(any: Any, property: KProperty<*>, s: String) {
        strData = s
    }
}

/**
 * 第二种:自定义委托类,继承ReadWriteProperty接口
 * ReadWriteProperty接口有两个泛型,
 * 第一个是委托属性所在的类及其父类(TestAgency/Any)
 * 第二个是委托属性的类型
 *
 * 好处:getValue和setValue方法通过继承ReadWriteProperty接口实现
 */
class CustomAgencyString02:ReadWriteProperty<Any,String>{
    var strData:String = "我是CustomAgency02"
    override fun getValue(thisRef: Any, property: KProperty<*>): String {
        return strData
    }

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

}

/**
 * 第一种:自定义委托类
 */
class CustomAgencyInt {
    operator fun getValue(testAgency: TestAgency, property: KProperty<*>): Int {
        return 10
    }
}

/**
 * 第二种:自定义委托类 通过继承ReadOnlyProperty实现
 */
class CustomAgencyInt02:ReadOnlyProperty<Any,Int> {
    override fun getValue(thisRef: Any, property: KProperty<*>): Int {
        return 20
    }

}

fun main() {
    var testAgency = TestAgency()

    println(testAgency.str)
    testAgency.str = "我是CustomAgency修改过后的数据"
    println(testAgency.str)
    println(testAgency.str02)

    println()
    println(testAgency.finalNum)
    println(testAgency.finalNum02)
}

by lazy (委托+懒加载)-特殊的委托类

by lazy共同使用的时候。

by调用的是Lazy.kt的getValue函数

getValue函数返回数据了value。

value是?

value是Lazy接口中的属性,那实现类是谁?

时使用过lazy函数返回的SynchronizedLazyImpl类的实例。

lazy函数是一个参数是函数的函数。

返回SynchronizedLazyImpl类,SynchronizedLazyImpl类实现了Lazy接口

by lazy 实际使用的是SynchronizedLazyImpl类中的value,value是lazy操作符传入的方法的返回值。

package agency

/**
 * 属性委托给lazy函数 = 其本质还是委托给了类
 * lazy函数返回一个类
 *
 * by lazy  委托+懒加载  在使用的时候才加载。
 */
fun requestNum():Float{
    println("requestNum开始执行")
    return 0.5f
}
/**
 * 普通调用函数
 * 会在main() 之前运行,加载的时候就执行了requestNum()
 * requestNum()在加载requestNum变量时执行了一次。
 * main()中使用requestNum时不再执行。
 * 同java
 */
var requestNum = requestNum()


/**
 * by lazy
 *
 * by 委托
 *
 * lazy是一个函数,一个参数是函数的函数。
 *
 * 效果:
 * 在使用requestRetrun的时候才执行,且只执行一次,
 * 使用第二次及以后,只会输出结果
 * 在使用变量的时候才执行方法
 */
val requestRetrun:String by lazy{ requestData() }

fun requestData():String{
    println("requestData开始执行")
    Thread.sleep(1000)
    return "requestData 结果"
}


fun main() {
    println("开始运行")
    println(requestNum)
    println(requestNum)
    Thread.sleep(3000)

    println(requestRetrun)
    println(requestRetrun)
}

提供者委托

使用provideDelegate方法重载by操作符。

注意provideDelegate方法名不能写错。

package agency

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

/**
 * 提供者委托
 * 功能:
 * 可以根据情况选择不同的代理类,重载了by操作符
 */

/**
 * provideDelegate放在类的外边,是类的扩展函数,和放在类的内部效果一样
 */
operator fun AgencyProvideDelegate.provideDelegate(any: Any, prop: KProperty<*>): ReadWriteProperty<Any, String> {
    //如果委托属性的名称 = str,返回AgencyClass01,如果不等于str,返回AgencyClass02
    if (prop.name.equals("str")) {
        return AgencyClass01();
    } else {
        return AgencyClass02();
    }
}

class AgencyProvideDelegate {
    /**
     * provideDelegate重载by操作符
     * 参数:
     * 1.委托属性所在类或其父类
     * 2.固定KProperty<*>,委托属性的参数
     * 返回类型:ReadWriteProperty<Any,String>
     */
//    operator fun provideDelegate(any: Any,prop:KProperty<*>):ReadWriteProperty<Any,String>{
//        //如果委托属性的名称 = str,返回AgencyClass01,如果不等于str,返回AgencyClass02
//        if(prop.name.equals("str")){
//            return AgencyClass01();
//        }else{
//            return AgencyClass02();
//        }
//    }

}

class AgencyClass01 : ReadWriteProperty<Any, String> {
    var str = "AgencyClass01"
    override fun getValue(thisRef: Any, property: KProperty<*>): String {
        return str
    }

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

class AgencyClass02 : ReadWriteProperty<Any, String> {
    var str = "AgencyClass02"
    override fun getValue(thisRef: Any, property: KProperty<*>): String {
        return str
    }

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

class Agency01 {
    /**
     * 实际委托类是AgencyClass01
     * by操作符执行的AgencyProvideDelegate类的provideDelegate方法
     */
    var str: String by AgencyProvideDelegate()

    /**
     * 实际委托类是AgencyClass02
     * by操作符执行的AgencyProvideDelegate类的provideDelegate方法
     */
    var str02: String by AgencyProvideDelegate()//AgencyClass02代理
}

fun main() {
    var agency01 = Agency01()
    println(agency01.str)
    println(agency01.str02)
}

 

实际案例-属性与控件双向绑定

属性与控件的双向绑定。

是Jetpack DataBinding的原理。

/**
 * 给TextView类扩展了provideDelegate方法,用于重载by操作符
 * 功能:
 * 将str属性委托给textview控件的text属性
 * 实现了str属性和TextView控件的双向绑定,即修改str属性会修改textview控件的text属性,修改textview控件的text属性会修改str属性
 */
operator fun TextView.provideDelegate (any: Any?,prop: KProperty<*>):ReadWriteProperty<Any?,String?> {
    return object:ReadWriteProperty<Any?,String?>{
        override fun getValue(thisRef: Any?, property: KProperty<*>): String? {
            return text.toString()
        }

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

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var textview: TextView = findViewById(R.id.textview)

        //str属性委托给textview控件
        var str:String? by textview

        str = "我是通过str变量修改的"

        textview.text = "我是通过textview控件修改的"
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2083952.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

黑神话悟空-画质提升+帧数提升+超宽屏+写实画质补丁+无光追也可拥有的超强画质

超真实画质提升&#xff01;&#xff01;&#xff01; 下载地址&#xff1a;https://pan.quark.cn/s/529202fbbbef

Python | Leetcode Python题解之第381题O(1)时间插入、删除和获取随机元素-允许重复

题目&#xff1a; 题解&#xff1a; import random class RandomizedCollection:def __init__(self):"""Initialize your data structure here."""self.table {}self.ns []def insert(self, val: int) -> bool:"""Inserts …

WPF 手撸插件 七 日志记录(二)

1、本文使用Serilog进行记录日志&#xff0c;目前想只用log4net进行日志记录&#xff0c;但是Serilog有想学习一下&#xff0c;所有这里使用控制台项目来学习一下Serilog。我使用的还是.Net Framework 4.5. 2、NuGet 安装Serilog 2.12.0、Serilog.Sinks.Console 4.1.0&#xf…

智能学习辅助系统——后端部分

目录 前言 一、准备工作 1.需求&环境搭建 1.1需求说明 1.2环境搭建 2.开发规范 2.1 开发规范-REST 2.2 开发规范-统一响应结果 3.开发流程 二、部门管理 1.查询部门 &#xff08;1&#xff09;原型和需求 &#xff08;2&#xff09;接口文档 &#xff08;3&…

阿里巴巴1688 阿里228滑块 网站分析(不涉及逆向)

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 有相关问题请第一时间头像私信联系我…

R语言统计分析——回归模型深层次分析

参考资料&#xff1a;R语言实战【第2版】 本文主要讨论回归模型的泛化能力和变量相对重要性的方法。 1、交叉验证 从定义上看&#xff0c;回归方法就是从一堆数据中获取最优模型参数。对于OLS&#xff08;普通最小二乘&#xff09;回归&#xff0c;通过使得预测误差&#xff0…

【书生大模型实战营(暑假场)】进阶任务六 MindSearch CPU-only 版部署

进阶任务六 MindSearch CPU-only 版部署 任务文档GitHub CodeSpace硅基流动HuggingFace Space 任务&#xff1a; MindSearch 部署到Github Codespace 和 Hugging Face Space 笔者部署在 HuggingFace 的 MindSearch 模型链接为&#xff1a;ccdgyro/MindSearch 1 开发机创建和环…

重塑视频监控体验:WebRTC技术如何赋能智慧工厂视频高效管理场景

视频汇聚EasyCVR视频监控平台&#xff0c;作为一款智能视频监控综合管理平台&#xff0c;凭借其强大的视频融合汇聚能力和灵活的视频能力&#xff0c;在各行各业的应用中发挥着越来越重要的作用。 EasyCVR平台不仅兼容多种主流标准协议及私有协议/SDK的接入&#xff08;如&…

汽车线束品牌服务商推荐-力可欣:致力于汽车连接线束和汽车连接器的开发、生产和应用

汽车线束品牌服务商推荐-力可欣&#xff1a;致力于汽车连接线束和汽车连接器的开发、生产和应用

医院建筑的电气设计——保障医疗质量与安全的坚固基石

医疗资源与水平的提升成为了衡量民生福祉的重要标尺。随着一批批新建医院及既有医院的华丽蜕变&#xff0c;从社区医院到综合医院&#xff0c;再到医疗城、医疗集聚区的崛起&#xff0c;不仅彰显了政府对民生健康的深切关怀&#xff0c;也预示着我国医疗体系正迈向智能化、高效…

C++初学(17)

17.1、字符函数库cctype C有一个与字符相关的、非常方便的函数软件包&#xff0c;它可以简化如确定字符是否为大写字母、数字或标点符号等工作。这些函数的原型是在头文件cctype中定义的。如果ch是一个字母&#xff0c;则isalpha(ch)函数返回一个非零值&#xff0c;否则返回0。…

关于zotero无法识别拖入的pdf和caj的题录信息

一、首先要安装好茉莉花插件 1、点击链接&#xff0c;进入Zotero 插件商店&#xff0c; Zotero 插件商店 | Zotero 中文社区 (zotero-chinese.com) 搜索&#xff1a;Jasminum&#xff0c;选择好版本&#xff0c;点击下载 2、 下载好后&#xff0c;点击“工具”&#xff0c;…

兔子序列(c语言)

1.//描述 //兔子发现了一个数字序列&#xff0c;于是开始研究这个序列。兔子觉得一个序列应该需要有一个命名&#xff0c; // 命名应该要与这个序列有关。由于兔子十分讨厌完全平方数&#xff0c; // 所以兔子开创了一个新的命名方式&#xff1a;这个序列中最大的不是完全平方数…

kubectl陈述式资源管理

目录 概念 kubectl的基础命令 *每天常用的查看集群的基本信息 deployment的部署方式 deployment 的特点 基于deployment创建pod 手动缩容 service的类型以及工作原理 创建service service的类型 修改service的类型为nodeport **nodeport实验&#xff1a;对外暴露端…

数据结构(Java)实现:栈和队列

文章目录 1. 栈的模拟实现1.1 普通栈的模拟实现1.2 泛型栈的模拟实现 2. 栈的介绍3. 栈的使用4. 栈的应用场景4.1 改变元素的序列4.2 将递归转换为循环4.3 使用栈解题 5. 栈的链表实现6. 队列概念7. 队列的使用8. 模拟队列的实现8.1 链式队列8.2 顺序队列 9. 双端队列 1. 栈的模…

C++和OpenGL实现3D游戏编程【连载6】——不规则图形的纹理贴图

C++和OpenGL实现3D游戏编程【连载6】——不规则图形的纹理贴图 1、本节实现的内容 上一节我们讨论了纹理贴图的相关基础操作,但上一节的纹理贴图操作基本上都是规则图形,包括圆形和球形虽然复杂一点,但是它也是规则的。这一节课我们要讨论一下,怎么在不规则图形上纹理贴图…

​polarctf靶场[web]upload1​

[web]upload1 考点&#xff1a;文件上传漏洞 不信邪&#xff0c;先上传php&#xff0c;发现被拦截 在上传jpg和png图片&#xff0c;发现也被拦截 所以先拦截抓包&#xff0c;上传个有一句话木马的png图片 将文件后缀改为php&#xff0c;先在重发器发送&#xff0c;发现上传成…

MATLAB 计算凹凸多边形的面积(85)

MATLAB 计算凹凸多边形的面积(84) 一、算法介绍二、算法实现1.代码一、算法介绍 计算凹凸多边形的面积,并输出计算结果,可视化 二、算法实现 1.代码 % 设置多边形的顶点坐标 % 这里以一个五边形为例 x = [1, 3, 4

深入理解DPO(Direct Preference Optimization)算法

目录 1. 什么是DPO&#xff1f;2. Bradley-Terry模型2.1 奖励模型的训练 3. 从PPO到DPO4. DPO的简单实现5. 梯度分析Ref 1. 什么是DPO&#xff1f; 直接偏好优化&#xff08;Direct Preference Optimization, DPO&#xff09;是一种不需要强化学习的对齐算法。由于去除了复杂的…

数分基础(03-2)客户特征分析-简单可视化

文章目录 简单可视化1. 并排柱状图2. 堆叠柱状图2.1 画图2.2 对数刻度 简单可视化 接上一篇 数分基础&#xff08;03-1&#xff09;客户特征分析&#xff0c;运行本篇代码之前&#xff0c;先运行上一篇的代码。 为了能够对比和总览三个客户群体Cluster 0 - Cluster 1 的特征&…