当前位置:网站首页>Kotlin1.6.20 new features context receivers tips

Kotlin1.6.20 new features context receivers tips

2022-06-22 20:32:00 1024 Q

Catalog

Preface

Limitations of extension functions

What is? Context Receivers

How to use Context Receivers

introduce Context Receivers Cause readability problems

Context Receivers Application scope and precautions

summary

Preface

Let's talk about this article Kotlin 1.6.20 New functions Context Receivers, Let's see what problems it solves for us .

Through this article, you will learn the following :

Limitations of extension functions

What is? Context Receivers, And how to use it

Context Receivers What problems have been solved

introduce Context Receivers It will bring new problems , How do we solve

Context Receivers Application scope and precautions

Limitations of extension functions

stay Kotlin The receiver in can only be applied to the extension function or with the receiver lambda Expression , As shown below .

class Context { var density = 0f}// spread function inline fun Context.px2dp(value: Int): Float = value.toFloat() / density

The recipient is fun After keyword and Type before point Context, There are two knowledge points hidden here .

We can call an internal function , Call the extension function px2dp(), Usually combined with Kotlin Scope function with , run , apply And so on .

with(Context()) { px2dp(100)}

Inside the extension function , We can use this keyword , Or hide keywords and implicitly access internal member functions , But we can't access private members

Extension functions are easy to use , We can extend the system or third-party library , But there are limitations .

Only one recipient can be defined , Therefore, its composability is limited , If there are multiple recipients, they can only be passed as parameters . Let's say we call px2dp() Method at the same time , Go to logcat and file Write log in .

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

stay Kotlin The receiver in can only be applied to the extension function or with the receiver lambda Expression , But it can't be used in ordinary functions , Lost flexibility

Context Receivers The emergence of brings new possibilities , It's a combination , Merge multiple context recipients together , More flexibility , Wider application .

What is? Context Receivers

Context Receivers Used to represent a basic constraint , That is, things that need to be done within certain scope under certain circumstances , It's more flexible , It can be combined , Organizational context , Group systems or third-party classes together , More functions .

If you want to use Context Receivers, Need to put Kotlin Plug in upgrade to 1.6.20 , And it can only be used after it is opened in the project .

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

When we finish the above configuration , You can use Context Receivers, Now let's transform the above case .

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

We are printf() On the function , Use context() keyword , stay context() Keywords in parentheses , Declare a list of context recipient types , Multiple types are separated by commas . However, the types listed cannot be repeated , No subtype relationship is allowed between them .

adopt context() Keyword to limit its scope , In this function , We can call context LogContext 、 FileContext Internal methods , But when it's used , Only through Kotlin Scope functions are nested to pass multiple recipients , Maybe in the future, it may provide a more elegant way .

with(LogContext()) { with(FileContext()) { printf("I am DHL") }} introduce Context Receivers Cause readability problems

If we were LogContext and FileContext Multiple variables or functions with the same name are declared in , We can only pass [email protected] To solve this problem .

context(LogContext, FileContext)fun printf(message: String) { logcat("print message in logcat ${[email protected]}") writeFile("write message in file ${[email protected]}")}

As you can see , stay LogContext and FileContext One of them is called name The variable of , We can only pass [email protected] Statement to access , But this will introduce a new problem , If there are a large number of variables or functions with the same name , It can lead to this Keywords are scattered everywhere , Resulting in poor readability . So we can isolate through the interface , To solve this problem .

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

By means of interface isolation , We can solve this The problem of poor readability caused by keywords , When using, you need to instantiate the interface .

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 Application scope and precautions

When we rewrite a function with a context acceptor , Must be declared as a context recipient of the same type .

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

We rewrote draw() function , The context recipient of the declaration must be the same ,Context Receivers It can not only act on the extension function 、 On ordinary functions , And it can also act on classes .

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

In the class LogHelp It has been used. context() keyword , We can do that LogHelp Use anywhere in the range LogContext perhaps FileContex.

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

Context Receivers In addition to acting on extension functions 、 Ordinary function 、 Class , It can also act on attributes getter and setter as well as lambda On the expression .

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

Finally, let's take a look , From the community Context Receivers Practical cases , Expand Json Tool class .

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

Context Receivers Provide a basic constraint , It can be within the specified range , Realize more functions through combination

Context Receivers Can act on extension functions 、 Ordinary function 、 class 、 attribute getter and setter 、 lambda expression

Context Receivers Allows you to... Without inheritance , By combination , Organizational context , Group systems or third-party classes together , More functions

adopt context() Keyword declaration , stay context() Keywords in parentheses , Declare a list of context recipient types , Multiple types are separated by commas

If used in large quantities this Keywords can lead to poor readability , We can solve this problem through interface isolation

When we rewrite a function with a context acceptor , Must be declared as a context recipient of the same type

That's all Kotlin1.6.20 function Context Receivers Details of using skills to uncover secrets , More about Kotlin1.6.20 function Context Receivers Please pay attention to other relevant articles of software development network !


原网站

版权声明
本文为[1024 Q]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/173/202206221905135592.html