最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Kotlin1.6.20新功能Context?Receivers使用技巧揭秘

 更新時(shí)間:2022年06月22日 16:30:10   作者:程序員DHL  
這篇文章主要為大家介紹了Kotlin1.6.20功能Context?Receivers使用揭秘,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

這篇文章我們一起來(lái)聊一下 Kotlin 1.6.20 的新功能 Context Receivers,來(lái)看看它為我們解決了什么問(wèn)題。

通過(guò)這篇文章將會(huì)學(xué)習(xí)到以下內(nèi)容:

  • 擴(kuò)展函數(shù)的局限性
  • 什么是 Context Receivers,以及如何使用
  • Context Receivers 解決了什么問(wèn)題
  • 引入 Context Receivers 會(huì)帶來(lái)新的問(wèn)題,我們?nèi)绾谓鉀Q
  • Context Receivers 應(yīng)用范圍及注意事項(xiàng)

擴(kuò)展函數(shù)的局限性

在 Kotlin 中接受者只能應(yīng)用在擴(kuò)展函數(shù)或者帶接受者 lambda 表達(dá)式中, 如下所示。

class Context {
    var density = 0f
}
// 擴(kuò)展函數(shù)
inline fun Context.px2dp(value: Int): Float = value.toFloat() / density

接受者是 fun 關(guān)鍵字之后點(diǎn)之前的類(lèi)型 Context,這里隱藏了兩個(gè)知識(shí)點(diǎn)。

  • 我們可以像調(diào)用內(nèi)部函數(shù)一樣,調(diào)用擴(kuò)展函數(shù) px2dp(),通常結(jié)合 Kotlin 作用域函數(shù) with , run , apply 等等一起使用。
with(Context()) {
    px2dp(100)
}
  • 在擴(kuò)展函數(shù)內(nèi)部,我們可以使用 this 關(guān)鍵字,或者隱藏關(guān)鍵字隱式訪問(wèn)內(nèi)部的成員函數(shù),但是我們不能訪問(wèn)私有成員

擴(kuò)展函數(shù)使用起來(lái)很方便,我們可以對(duì)系統(tǒng)或者第三方庫(kù)進(jìn)行擴(kuò)展,但是也有局限性。

  • 只能定義一個(gè)接受者,因此限制了它的可組合性,如果有多個(gè)接受者只能當(dāng)做參數(shù)傳遞。比如我們調(diào)用 px2dp() 方法的同時(shí),往 logcat 和 file 中寫(xiě)入日志。
class LogContext {
    fun logcat(message: Any){}
}
class FileContext {
    fun writeFile(message: Any) {}
}
fun printf(logContext: LogContext, fileContext: FileContext) {
    with(Context()) {
        val dp = px2dp(100)
        logContext.logcat("print ${dp} in logcat")
        fileContext.writeFile("write ${dp} in file")
    }
}
  • 在 Kotlin 中接受者只能應(yīng)用在擴(kuò)展函數(shù)或者帶接受者 lambda 表達(dá)式中,卻不能在普通函數(shù)中使用,失去了靈活性

Context Receivers 的出現(xiàn)帶來(lái)新的可能性,它通過(guò)了組合的方式,將多個(gè)上下文接受者合并在一起,靈活性更高,應(yīng)用范圍更廣。

什么是 Context Receivers

Context Receivers 用于表示一個(gè)基本約束,即在某些情況下需要在某些范圍內(nèi)才能完成的事情,它更加的靈活,可以通過(guò)組合的方式,組織上下文,將系統(tǒng)或者第三方類(lèi)組合在一起,實(shí)現(xiàn)更多的功能。

如果想在項(xiàng)目中使用 Context Receivers,需要將 Kotlin 插件升級(jí)到 1.6.20 ,并且在項(xiàng)目中開(kāi)啟才可以使用。

plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.6.20'
}
// ......
kotlinOptions {
    freeCompilerArgs = ["-Xcontext-receivers"]
}

如何使用 Context Receivers

當(dāng)我們完成上述配置之后,就可以在項(xiàng)目中使用 Context Receivers,現(xiàn)在我們將上面的案例改造一下。

context(LogContext, FileContext)
fun printf() {
    with(Context()) {
        val dp = px2dp(100)
        logContext.logcat("print ${dp} in logcat")
        fileContext.writeFile("write ${dp} in file")
    }
}

我們?cè)?printf() 函數(shù)上,使用 context() 關(guān)鍵字,在 context() 關(guān)鍵字括號(hào)中,聲明上下文接收者類(lèi)型的列表,多個(gè)類(lèi)型用逗號(hào)分隔。但是列出的類(lèi)型不允許重復(fù),它們之間不允許有子類(lèi)型關(guān)系。

通過(guò) context() 關(guān)鍵字來(lái)限制它的作用范圍,在這個(gè)函數(shù)中,我們可以調(diào)用上下文 LogContext 、 FileContext 內(nèi)部的方法,但是使用的時(shí)候,只能通過(guò) Kotlin 作用域函數(shù)嵌套來(lái)傳遞多個(gè)接受者,也許在未來(lái)可能會(huì)提供更加優(yōu)雅的方式。

with(LogContext()) {
    with(FileContext()) {
        printf("I am DHL")
    }
}

引入 Context Receivers 導(dǎo)致可讀性問(wèn)題

如果我們?cè)?LogContext 和 FileContext 中聲明了多個(gè)相同名字的變量或者函數(shù),我們只能通過(guò) this@Lable 語(yǔ)句來(lái)解決這個(gè)問(wèn)題。

context(LogContext, FileContext)
fun printf(message: String) {
    logcat("print message in logcat ${this@LogContext.name}")
    writeFile("write message in file ${this@FileContext.name}")
}

正如你所見(jiàn),在 LogContext 和 FileContext 中都有一個(gè)名為 name 的變量,我們只能通過(guò) this@Lable 語(yǔ)句來(lái)訪問(wèn),但是這樣會(huì)引入一個(gè)新的問(wèn)題,如果有大量的同名的變量或者函數(shù),會(huì)導(dǎo)致 this 關(guān)鍵字分散到處都是,造成可讀性很差。所以我們可以通過(guò)接口隔離的方式,來(lái)解決這個(gè)問(wèn)題。

interface LogContextInterface{
    val logContext:LogContext
}
interface FileContextInterface{
    val fileContext:FileContext
}
context(LogContextInterface, FileContextInterface)
fun printf(message: String) {
    logContext.logcat("print message in logcat ${logContext.name}")
    fileContext.writeFile("write message in file ${fileContext.name}")
}

通過(guò)接口隔離的方式,我們就可以解決 this 關(guān)鍵字導(dǎo)致的可讀性差的問(wèn)題,使用的時(shí)候需要實(shí)例化接口。

val logContext = object : LogContextInterface {
    override val logContext: LogContext = LogContext()
}
val fileContext = object : FileContextInterface {
    override val fileContext: FileContext = FileContext()
}
with(logContext) {
    with(fileContext) {
        printf("I am DHL")
    }
}

Context Receivers 應(yīng)用范圍及注意事項(xiàng)

當(dāng)我們重寫(xiě)帶有上下文接受者的函數(shù)時(shí),必須聲明為相同類(lèi)型的上下文接受者。

interface Canvas
interface Shape {
    context(Canvas)
    fun draw()
}
class Circle : Shape {
    context(Canvas)
    override fun draw() {
    }
}

我們重寫(xiě)了 draw() 函數(shù),聲明的上下文接受者必須是相同的,Context Receivers 不僅可以作用在擴(kuò)展函數(shù)、普通函數(shù)上,而且還可以作用在類(lèi)上。

context(LogContextInterface, FileContextInterface)
class LogHelp{
    fun printf(message: String) {
        logContext.logcat("print message in logcat ${logContext.name}")
        fileContext.writeFile("write message in file ${fileContext.name}")
    }
}

在類(lèi) LogHelp 上使用了 context() 關(guān)鍵字,我們就可以在 LogHelp 范圍內(nèi)任意的地方使用 LogContext 或者 FileContex。

val logHelp = with(logContext) {
    with(fileContext) {
        LogHelp()
    }
}
logHelp.printf("I am DHL")

Context Receivers 除了作用在擴(kuò)展函數(shù)、普通函數(shù)、類(lèi)上,還可以作用在屬性 getter 和 setter 以及 lambda 表達(dá)式上。

context(View)
val Int.dp get() = this.toFloat().dp
// lambda 表達(dá)式
fun save(block: context(LogContextInterface) () -> Unit) {
}

最后我們來(lái)看一下,來(lái)自社區(qū) Context Receivers 實(shí)踐的案例,擴(kuò)展 Json 工具類(lèi)。

fun json(build: JSONObject.() -> Unit) = JSONObject().apply { build() }
context(JSONObject)
infix fun String.by(build: JSONObject.() -> Unit) = put(this, JSONObject().build())
context(JSONObject)
infix fun String.by(value: Any) = put(this, value)
fun main() {
    val json = json {
        "name" by "Kotlin"
        "age" by 10
        "creator" by {
            "name" by "JetBrains"
            "age" by "21"
        }
    }
}

總結(jié)

  • Context Receivers 提供一個(gè)基本的約束,可以在指定范圍內(nèi),通過(guò)組合的方式實(shí)現(xiàn)更多的功能
  • Context Receivers 可以作用在擴(kuò)展函數(shù)、普通函數(shù)、類(lèi)、屬性 getter 和 setter 、 lambda 表達(dá)式
  • Context Receivers 允許在不需要繼承的情況,通過(guò)組合的方式,組織上下文,將系統(tǒng)或者第三方類(lèi)組合在一起,實(shí)現(xiàn)更多的功能
  • 通過(guò) context() 關(guān)鍵字聲明,在 context() 關(guān)鍵字括號(hào)中,聲明上下文接收者類(lèi)型的列表,多個(gè)類(lèi)型用逗號(hào)分隔
  • 如果大量使用 this 關(guān)鍵字會(huì)導(dǎo)致可讀性變差,我們可以通過(guò)接口隔離的方式來(lái)解決這個(gè)問(wèn)題
  • 當(dāng)我們重寫(xiě)帶有上下文接受者的函數(shù)時(shí),必須聲明為相同類(lèi)型的上下文接受者

以上就是Kotlin1.6.20功能Context Receivers使用技巧揭秘的詳細(xì)內(nèi)容,更多關(guān)于Kotlin1.6.20功能Context Receivers的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

衢州市| 突泉县| 嘉鱼县| 静宁县| 绩溪县| 白沙| 紫阳县| 海淀区| 岢岚县| 砀山县| 广德县| 商河县| 潜山县| 中宁县| 新津县| 景泰县| 陈巴尔虎旗| 拉萨市| 建阳市| 天水市| 南康市| 高平市| 昌黎县| 汝南县| 常熟市| 延安市| 土默特右旗| 吴堡县| 扎兰屯市| 古蔺县| 板桥市| 商河县| 延津县| 红桥区| 开鲁县| 通城县| 浏阳市| 水富县| 昆明市| 高台县| 太和县|