網站首頁 編程語言 正文
1.Kotlin委托
在委托模式中,兩個對象參與處理同一請求,接受請求的對象講請求委托給另外一個對象來處理。Kotlin直接支持委托模式,更加優雅,簡潔。kotlin通過關鍵字by
實現委托。
2.類委托
類的委托即一個類中定義的方法實際是調用另一個類的對象的方法來實現的。
以下實例中派生類Derived繼承了接口Base所有方法,并且委托一個傳入的Base類的對象來執行這些方法。
//創建接口 interface Base { fun print() } //實現此接口的被委托的類 class BaseImp(val x:Int) : Base { override fun print() { println(x) } } //通過關鍵字by建立委托類 class Derived (b:Base):Base by b class Main { companion object{ @JvmStatic fun main(args: Array<String>) { var baseImp=BaseImp(100) Derived(baseImp).print() //輸出100 } } }
在Derived聲明中,by子句表示,將b保存在Derived的對象實例內部,而且編譯器將會生成繼承自Base接口的所有方法,并將調用轉發給b。我們看看生成的java代碼。
public final class Derived implements Base { // $FF: synthetic field private final Base $$delegate_0; public Derived(@NotNull Base b) { Intrinsics.checkNotNullParameter(b, "b"); super(); this.$$delegate_0 = b; } public void print() { this.$$delegate_0.print(); } }
3.屬性委托
屬性委托指的是一個類的某個屬性值不是在類中直接進行定義,而是將其委托給一個代理類,從而實現對該類的屬性統一管理。
屬性委托語法格式:
val/var <屬性名>:<類型> by <表達式>
by關鍵字之后的表達式就是委托,屬性的get()方法(以及set()方法)將被委托給這個對象的getValue()和setValue()方法。屬性委托不必實現任何接口,但是必須提供getValue()函數(對于var屬性,還需要setValue()函數)。
3.1定義一個被委托的類
該類包含getValue()方法和setValue()方法,且參數thisRef為進行委托的類的對象,prop為進行委托的屬性的對象。
//定義包含屬性委托的類 class Example { var p:String by Delegate() } //委托的類 open class Delegate { operator fun getValue(thisRef:Any?,property:KProperty<*>):String{ return "$thisRef,這里委托了${property.name} 屬性" } operator fun setValue(thisRef: Any?,property: KProperty<*>,value:String){ println("$thisRef 的 ${property.name} 屬性賦值為 $value") } } class Main { companion object{ @JvmStatic fun main(args: Array<String>) { var e=Example() println(e.p) //訪問該屬性 調用getValue函數 e.p="rururn" //調用setValue()函數 println(e.p) } } }
輸出結構為:
com.geespace.lib.kotlin.by2.Example@3f99bd52,這里委托了p 屬性
com.geespace.lib.kotlin.by2.Example@3f99bd52 的 p 屬性賦值為 rururn
com.geespace.lib.kotlin.by2.Example@3f99bd52,這里委托了p 屬性
3.2標準委托
Kotlin的標準庫已經內置了很多工廠方法來實現屬性的委托。
延遲屬性Lazy
lazy()是一個函數,接受一個Lambda表達式作為參數,返回一個Lazy<T>實例的函數,返回的實例可以作為延遲屬性的委托:第一次調用get()會執行已傳遞給lazy()的lamda表達式并記錄結果,后續調用get()只是返回記錄的結果。
class LazyTest { companion object{ val lazyValue:String by lazy { println("computed!") //第一次調用輸出,第二次調用不執行 "Hello" } @JvmStatic fun main(args: Array<String>) { println(lazyValue) println(lazyValue) } } }
執行輸出結果:
computed!
Hello
Hello
3.3把屬性存儲在映射中
一個常見的用例是在一個映射(map)里存儲屬性的值。這經常出現在像解析JSON或者其他"動態"事情的應用中。這種情況下,你可以使用映射實例自身作為委托來實現委托屬性。
class Site(val map:Map<String,Any?>) { val name:String by map val url:String by map } class TestMain { companion object{ @JvmStatic fun main(args: Array<String>) { val site=Site(mapOf( "name" to "maozh", "url" to "www.baidu.com" )) //讀取映射值 println(site.name) println(site.url) } } }
執行輸出結果:
maozh
www.baidu.com
3.4Not Null
notNull適用于那些無法在初始化階段就確定屬性值的場合。
class Foo{ var notNullBar:String by Delegates.notNull<String>() } foo.notNullBar="bar" println(foo.notNullBar)
需要注意,如果屬性在賦值前就被訪問的話則會拋出異常。
原文鏈接:https://blog.csdn.net/Goals1989/article/details/127179137
相關推薦
- 2022-12-27 詳解PyQt5?事件處理機制_python
- 2023-07-08 css如何給div添加一個條紋背景,在背景上畫一條有寬度的斜線
- 2022-12-24 Python中通過@classmethod?實現多態的示例_python
- 2023-07-25 使用SpringBoot+JWT+MybatisPlus實現簡單的登陸狀態驗證
- 2022-10-10 VMware?Workstation與Device/Credential?Guard不兼容的解決_V
- 2022-05-03 C#面向對象設計原則之接口隔離原則_C#教程
- 2022-04-21 Python?數據類型中的字符串和數字_python
- 2023-07-26 TypeScript中的類型聲明declare
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支