返回顶部
首页 > 资讯 > 精选 >Kotlin1.6.20新功能Context Receivers怎么使用
  • 742
分享到

Kotlin1.6.20新功能Context Receivers怎么使用

2023-07-02 12:07:36 742人浏览 独家记忆
摘要

本篇内容介绍了“Kotlin1.6.20新功能Context Receivers怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所

本篇内容介绍了“Kotlin1.6.20新功能Context Receivers怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

扩展函数的局限性

在 Kotlin 中接受者只能应用在扩展函数或者带接受者 lambda 表达式中, 如下所示。

class Context {    var density = 0f}// 扩展函数inline fun Context.px2dp(value: Int): Float = value.toFloat() / density

接受者是 fun 关键字之后点之前的类型 Context,这里隐藏了两个知识点。

  • 我们可以像调用内部函数一样,调用扩展函数 px2dp(),通常结合 Kotlin 作用域函数 with , run , apply 等等一起使用。

with(Context()) {    px2dp(100)}
  • 在扩展函数内部,我们可以使用 this 关键字,或者隐藏关键字隐式访问内部的成员函数,但是我们不能访问私有成员

扩展函数使用起来很方便,我们可以对系统或者第三方库进行扩展,但是也有局限性。

  • 只能定义一个接受者,因此限制了它的可组合性,如果有多个接受者只能当做参数传递。比如我们调用 px2dp() 方法的同时,往 loGCat 和 file 中写入日志

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 中接受者只能应用在扩展函数或者带接受者 lambda 表达式中,却不能在普通函数中使用,失去了灵活性

Context Receivers 的出现带来新的可能性,它通过了组合的方式,将多个上下文接受者合并在一起,灵活性更高,应用范围更广。

什么是 Context Receivers

Context Receivers 用于表示一个基本约束,即在某些情况下需要在某些范围内才能完成的事情,它更加的灵活,可以通过组合的方式,组织上下文,将系统或者第三方类组合在一起,实现更多的功能。

如果想在项目中使用 Context Receivers,需要将 Kotlin 插件升级到 1.6.20 ,并且在项目中开启才可以使用。

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

如何使用 Context Receivers

当我们完成上述配置之后,就可以在项目中使用 Context Receivers,现在我们将上面的案例改造一下。

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

我们在 printf() 函数上,使用 context() 关键字,在 context() 关键字括号中,声明上下文接收者类型的列表,多个类型用逗号分隔。但是列出的类型不允许重复,它们之间不允许有子类型关系。

通过 context() 关键字来限制它的作用范围,在这个函数中,我们可以调用上下文 LogContext 、 FileContext 内部的方法,但是使用的时候,只能通过 Kotlin 作用域函数嵌套来传递多个接受者,也许在未来可能会提供更加优雅的方式。

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

引入 Context Receivers 导致可读性问题

如果我们在 LogContext 和 FileContext 中声明了多个相同名字的变量或者函数,我们只能通过 this@Lable 语句来解决这个问题。

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

正如你所见,在 LogContext 和 FileContext 中都有一个名为 name 的变量,我们只能通过 this@Lable 语句来访问,但是这样会引入一个新的问题,如果有大量的同名的变量或者函数,会导致 this 关键字分散到处都是,造成可读性很差。所以我们可以通过接口隔离的方式,来解决这个问题。

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}")}

通过接口隔离的方式,我们就可以解决 this 关键字导致的可读性差的问题,使用的时候需要实例化接口。

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 应用范围及注意事项

当我们重写带有上下文接受者的函数时,必须声明为相同类型的上下文接受者。

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

我们重写了 draw() 函数,声明的上下文接受者必须是相同的,Context Receivers 不仅可以作用在扩展函数、普通函数上,而且还可以作用在类上。

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}")    }}

在类 LogHelp 上使用了 context() 关键字,我们就可以在 LogHelp 范围内任意的地方使用 LogContext 或者 FileContex。

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

Context Receivers 除了作用在扩展函数、普通函数、类上,还可以作用在属性 getter 和 setter 以及 lambda 表达式上。

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

最后我们来看一下,来自社区 Context Receivers 实践的案例,扩展 JSON 工具类。

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"        }    }}

“Kotlin1.6.20新功能Context Receivers怎么使用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: Kotlin1.6.20新功能Context Receivers怎么使用

本文链接: https://lsjlt.com/news/341748.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Kotlin1.6.20新功能Context Receivers怎么使用
    本篇内容介绍了“Kotlin1.6.20新功能Context Receivers怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所...
    99+
    2023-07-02
  • Kotlin1.6.20新功能Context Receivers使用技巧揭秘
    目录前言扩展函数的局限性什么是 Context Receivers如何使用 Context Receivers引入 Context Receivers 导致可读性问题Context ...
    99+
    2024-04-02
  • TypeScript4.0的新功能怎么使用
    这篇文章主要介绍“TypeScript4.0的新功能怎么使用”,在日常操作中,相信很多人在TypeScript4.0的新功能怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”TypeScript4.0的新...
    99+
    2023-06-27
  • go语言context包功能及操作使用详解
    目录Context包到底是干嘛用的?context原理什么时候应该使用 Context?如何创建 Context?主协程通知有子协程,子协程又有多个子协程context核心接口emp...
    99+
    2024-04-02
  • 怎么使用数据库新功能PL/SCOPE
    本篇内容主要讲解“怎么使用数据库新功能PL/SCOPE”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用数据库新功能PL/SCOPE”吧!我在会话中打开PL...
    99+
    2024-04-02
  • react中context怎么使用
    今天小编给大家分享一下react中context怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来...
    99+
    2024-04-02
  • go语言context包功能及操作使用的方法
    本篇内容介绍了“go语言context包功能及操作使用的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Context包到底是干嘛用的?我...
    99+
    2023-06-30
  • Spring5新功能日志框架Log4j2怎么使用
    这篇文章主要讲解了“Spring5新功能日志框架Log4j2怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring5新功能日志框架Log4j2怎么使用”吧!Spring5整合Lo...
    99+
    2023-06-30
  • Go中的Context怎么使用
    这篇“Go中的Context怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Go中的Context怎么使用”文章吧。1...
    99+
    2023-07-06
  • 使用AJAX怎么实现无刷新分页功能
    使用AJAX怎么实现无刷新分页功能,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。  首先讲一下原理:分页有两个要点:1.有多少页,2.每页有多...
    99+
    2024-04-02
  • 怎么使用Python功能
    这篇文章主要讲解了“怎么使用Python功能”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用Python功能”吧!变量赋值正如函数*args和**kwargs,在变量赋值中可以运用相同...
    99+
    2023-06-16
  • 怎么使用ADO.NET功能
    这篇文章主要为大家展示了“怎么使用ADO.NET功能”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“怎么使用ADO.NET功能”这篇文章吧。ADO.NET功能作为一个高效的.NET程序语言。其混合...
    99+
    2023-06-17
  • ASP.NET 2.0功能怎么使用
    这篇文章主要介绍“ASP.NET 2.0功能怎么使用”,在日常操作中,相信很多人在ASP.NET 2.0功能怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”ASP.NET 2.0功能怎么使用”的疑惑有所...
    99+
    2023-06-17
  • webpack5的功能怎么使用
    这篇文章主要介绍了webpack5的功能怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇webpack5的功能怎么使用文章都会有所收获,下面我们一起来看看吧。功能清除清理已弃用的功能所有在 webpack...
    99+
    2023-06-27
  • Java Arrays.copyOf功能怎么使用
    本文小编为大家详细介绍“Java Arrays.copyOf功能怎么使用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java Arrays.copyOf功能怎么使用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入...
    99+
    2023-07-05
  • SpringBoot怎么新增脱敏功能
    这篇“SpringBoot怎么新增脱敏功能”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“SpringBoot怎么新增脱敏功能...
    99+
    2023-07-04
  • ES6新数据结构Map功能怎么用
    这篇文章主要介绍ES6新数据结构Map功能怎么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!具体如下:新数据结构MapJavaScript中对象的本质是键值对的集合,但是键只能是字...
    99+
    2024-04-02
  • VSTS 2010客户端IDE新功能怎么用
    小编给大家分享一下VSTS 2010客户端IDE新功能怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!本文要介绍的是VSTS 2010客户端IDE的一个新功能...
    99+
    2023-06-17
  • Oracle中怎么创建和使用Context Indexes
    在Oracle中,Context Indexes用于全文搜索,可以使用Oracle Text技术来创建和使用。以下是创建和使用Con...
    99+
    2024-04-19
    Oracle
  • JDK 1.5 新功能使用实例之Generics
    Generics 是JDK 1.5 一个最重要的特性,主要用来处理Collection。   以下代码在JDK 1.5 调试通过。  代码实例1: Demo.javapackage maoxiang.examples.jdk15.gener...
    99+
    2023-06-03
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作