在Kotlin中,委托属性(Delegated Properties)是一种强大的语言特性,允许你将属性的 getter 和 setter 方法的实现委托给其他对象。这使得你能够通过委托来重用代码、将属性的行为解耦,并实现一些通用的模式。下面是一些关键概念和用法:

  1. class Example {
  2. var property: String by Delegate()
  3. }
  4.  
  5. class Delegate {
  6. operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
  7. // 获取属性值的实际实现
  8. return "Delegated value"
  9. }
  10.  
  11. operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
  12. // 设置属性值的实际实现
  13. println("Setting value to: $value")
  14. }
  15. }

在上面的代码中,Example类中的property属性的访问,比如,访问example.property,就会委托到Delegate.getValue; 属性值的设置example.property = "str",就会委托到

Delegae.setValue。

实际例子:

  1. fun saveCookie(url: String?, domain: String?, cookies: String) {
  2. url ?: return
  3. var spUrl: String by Preference(url, cookies)
  4. @Suppress("UNUSED_VALUE")
  5. spUrl = cookies
  6. domain ?: return
  7. var spDomain: String by Preference(domain, cookies)
  8. @Suppress("UNUSED_VALUE")
  9. spDomain = cookies
  10. }

var spUrl: String by Preference(url, cookies),定义一个委托属性spUrl,Preference委托,执行spUrl = cookies,会将这个setValue的动作委托到Preference类中的setValue。

  1. operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
  2. putSharedPreferences(name, value)
  3. }

其中value的值是cookies.如果要访问spUrl,那么,对应的getValue方法,会被委托到Preference中的getValue方法中去。

总结来说:

委托属性,就是将一个属性的getValue方法和setValue方法委托到另外一个代理类来实现。将属性的获取和设置隔离开来。

  1. class Preference<T>(val name: String, private val default: T) {
  2.  
  3. companion object {
  4. private val file_name = "wan_android_file"
  5.  
  6. private val prefs: SharedPreferences by lazy {
  7. App.context.getSharedPreferences(file_name, Context.MODE_PRIVATE)
  8. }
  9.  
  10. /**
  11. * 删除全部数据
  12. */
  13. fun clearPreference() {
  14. prefs.edit().clear().apply()
  15. }
  16.  
  17. /**
  18. * 根据key删除存储数据
  19. */
  20. fun clearPreference(key: String) {
  21. prefs.edit().remove(key).apply()
  22. }
  23.  
  24. /**
  25. * 查询某个key是否已经存在
  26. *
  27. * @param key
  28. * @return
  29. */
  30. fun contains(key: String): Boolean {
  31. return prefs.contains(key)
  32. }
  33.  
  34. /**
  35. * 返回所有的键值对
  36. *
  37. * @param context
  38. * @return
  39. */
  40. fun getAll(): Map<String, *> {
  41. return prefs.all
  42. }
  43. }
  44.  
  45. operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
  46. return getSharedPreferences(name, default)
  47. }
  48.  
  49. operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
  50. putSharedPreferences(name, value)
  51. }
  52.  
  53. @SuppressLint("CommitPrefEdits")
  54. private fun putSharedPreferences(name: String, value: T) = with(prefs.edit()) {
  55. when (value) {
  56. is Long -> putLong(name, value)
  57. is String -> putString(name, value)
  58. is Int -> putInt(name, value)
  59. is Boolean -> putBoolean(name, value)
  60. is Float -> putFloat(name, value)
  61. else -> putString(name, serialize(value))
  62. }.apply()
  63. }
  64.  
  65. @Suppress("UNCHECKED_CAST")
  66. private fun getSharedPreferences(name: String, default: T): T = with(prefs) {
  67. val res: Any = when (default) {
  68. is Long -> getLong(name, default)
  69. is String -> getString(name, default) ?: ""
  70. is Int -> getInt(name, default)
  71. is Boolean -> getBoolean(name, default)
  72. is Float -> getFloat(name, default)
  73. else -> deSerialization(getString(name, serialize(default)) ?: "")
  74. }
  75. return res as T
  76. }
  77.  
  78. /**
  79. * 序列化对象
  80.  
  81. * @param person
  82. * *
  83. * @return
  84. * *
  85. * @throws IOException
  86. */
  87. @Throws(IOException::class)
  88. private fun <A> serialize(obj: A): String {
  89. val byteArrayOutputStream = ByteArrayOutputStream()
  90. val objectOutputStream = ObjectOutputStream(
  91. byteArrayOutputStream
  92. )
  93. objectOutputStream.writeObject(obj)
  94. var serStr = byteArrayOutputStream.toString("ISO-8859-1")
  95. serStr = java.net.URLEncoder.encode(serStr, "UTF-8")
  96. objectOutputStream.close()
  97. byteArrayOutputStream.close()
  98. return serStr
  99. }
  100.  
  101. /**
  102. * 反序列化对象
  103.  
  104. * @param str
  105. * *
  106. * @return
  107. * *
  108. * @throws IOException
  109. * *
  110. * @throws ClassNotFoundException
  111. */
  112. @Suppress("UNCHECKED_CAST")
  113. @Throws(IOException::class, ClassNotFoundException::class)
  114. private fun <A> deSerialization(str: String): A {
  115. val redStr = java.net.URLDecoder.decode(str, "UTF-8")
  116. val byteArrayInputStream = ByteArrayInputStream(
  117. redStr.toByteArray(charset("ISO-8859-1"))
  118. )
  119. val objectInputStream = ObjectInputStream(
  120. byteArrayInputStream
  121. )
  122. val obj = objectInputStream.readObject() as A
  123. objectInputStream.close()
  124. byteArrayInputStream.close()
  125. return obj
  126. }
  127.  
  128. }

Kotlin委托属性(1)的更多相关文章

  1. kotlin委托属性

    fun main(arg: Array<String>) { val myClass1 = myClass1() myClass1.name="mycalsss1" v ...

  2. ViewBinding 与 Kotlin 委托双剑合璧

    请点赞关注,你的支持对我意义重大. Hi,我是小彭.本文已收录到 GitHub · Android-NoteBook 中.这里有 Android 进阶成长知识体系,有志同道合的朋友,关注公众号 [彭旭 ...

  3. Kotlin的属性委托:无上下文情况下Android的赋值(KAD 15)

    作者:Antonio Leiva 时间:Mar 9, 2017 原文链接:https://antonioleiva.com/property-delegation-kotlin/ 如我们在前面文章中读 ...

  4. kotlin 委托

    委托模式是软件设计模式中的一项基本技巧.在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理. Kotlin 直接支持委托模式,更加优雅,简洁.Kotlin 通过关键 ...

  5. Kotlin 委托(1)类委托、变量委托注意事项

    1.官方文档 英文: https://kotlinlang.org/docs/reference/delegation.html https://kotlinlang.org/docs/referen ...

  6. Kotlin代理属性--官方文档翻译

    代理属性 Delegated Properties 本文为个人翻译的Kotlin官方文档, 原文连接: Delegated Properties 一些特定的常见类型的属性, 尽管我们可以在每次需要的时 ...

  7. Kotlin 委托(2)变量委托是什么、自定义变量委托

    1.委托是什么? 1.1 官网示例 在每个变量委托的实现的背后,Kotlin 编译器都会生成辅助对象并委托给它. 假设委托如下, class C { var prop: Type by MyDeleg ...

  8. python cookbook第三版学习笔记十七:委托属性

    我们想在访问实例的属性时能够将其委托到一个内部持有的对象上,这经常用到代理机制上 class A:     def spam(self,x):         print("class_A: ...

  9. kotlin 委托类的初始化函数

    import java.beans.AppletInitializer import kotlin.reflect.KProperty fun main(arg: Array<String> ...

  10. Android kotlin静态属性、静态方法

    只需要用 companion object 包裹相应代码块即可.以静态属性为例: class Constants { companion object { val BASE_URL = "h ...

随机推荐

  1. 用Rust手把手编写一个Proxy(代理), UDP绑定篇

    用Rust手把手编写一个Proxy(代理), UDP绑定篇 项目 ++wmproxy++ gite: https://gitee.com/tickbh/wmproxy github: https:// ...

  2. DevOps|研发效能团队组织架构和能力建设

    研发效能团队相对于各个公司主营业务规模来说并不是很大,但是在经历的几家公司里主要是有两种组织架构,职能独立型组织架构和业务闭环型组织架构.本文主要讲解这两种组织架构的特点.优劣.劣势. 业务闭环组织架 ...

  3. Django框架项目——redis操作、Celery

    1-redis操作 redis介绍 redis安装 """ 1.官网下载:安装包或是绿色面安装 2.安装并配置环境变量 """ redis ...

  4. 前端三件套系例之CSS——CSS3基础布局

    文章目录 css基础布局 1.布局相关的标签 2.盒子模型 2-1 什么是盒子模型 2-2 margin外边距 2-3 padding内填充 2-4 案例 3.浮动(float) 3-1 什么是浮动 ...

  5. ORACLE错误代码一览表,方便大家查询!

    ORACLE错误一览表,方便大家查询! ORA-00001: 违反唯一约束条件 (.) ORA-00017: 请求会话以设置跟踪事件 ORA-00018: 超出最大会话数 ORA-00019: 超出最 ...

  6. MySQL低配数据库被大量数据导入时KO

    在一个低配MySQL数据库(笔记本电脑虚机环境,虚机配置2CPU/3G内存),在3000万级别的大量数据LOAD DATA方式导入时,坚持一小时后,终于被KO了,甚至没写下任何有用的日志,只是在操作界 ...

  7. [最佳实践]配置sshd只允许sftp登录

    sftp 是 Secure File Transfer Protocol 的缩写,即安全文件传送协议,可为传输文件提供一种安全的加密方法. sftp 为 SSH 的一部分,由于这种传输方式使用了加密/ ...

  8. 惊奇!Android studio内部在调用Eclipse

    现在用Android studio的人越来越多,主要是说谷歌不再支持Eclipse,而力推Android studio.但是as也太不给力了,我之前写过一篇博客提到. 今天要说的是一个惊天的消息,如题 ...

  9. Flex 布局项目实战,好像没那么难!

    在上篇文章别再用 float 布局了,flex 才是未来!中,我们聊到 Flex 布局才是目前主流的布局方式.在文章最后,我们还贴了一个案例,并且还浅浅地讲解了一下. 有些小伙伴说,这讲解得太粗了,要 ...

  10. Linux账号密码安全运维

    前言 随着云计算厂商的兴起,云资源如ECS不再只有企业或者公司才会使用,普通人也可以自己买一台ECS来搭建自己的应用或者网站.虽然云计算厂商帮我们做了很多安全相关的工作,但并不代表我们的机器资源就绝对 ...