Kotlin extend the use and function of the difference between run, with, let, also and apply the

Overview

And compared to Java, it provides a lot of new features in Kotlin in. This time we have to chat Kotlin some generic extension functions run, with, let, also, and apply. For five expansion function they are present in the standard library source code Kotlin among them that is Standard.kt file. They are suitable for a general extension function of any object. But for the run, with, let, also, and apply these five functions and their usage is similar, so we can not determine to choose which one to use. So now we have to talk about the five function of their use, their differences and go in what scene.

Scope function

Here we look at the focus is on run, with, T.run, T.let, T.also, and T.apply, for these functions is one of their most important function is called internally and provide the function a scope.

Then the following about the scope run function for other functions is of course also a similar view through a piece of code.

fun test(){
    var animal = "cat"
    run {
        val animal = "dog"
        println(animal)   // dog
    }
    println(animal)       //cat
}

In this simple test function which we have an individual scope, you can redefine a variable in the run animal functions, and its scope exists only in run functions among.

At present, for this run function seems, it is not useful, but in the run function in which it is more than just a scope, he has a return value. He will return to the last object in the scope among.

For example, now have such a scenario, users receive app reward, if the user is not logged in pop-up login dialog, dialog receive awards if already logged in then ejected. We can use the following code to handle this logic.

run {
    if (islogin) loginDialog else getAwardDialog
}.show()

You can see the above code will become more simple, and can show a method applied to the above two dialog them, rather than to call twice.

with other generic and extended functions

Here the reason why the function with out alone explained, because with usage and other general usage was extended functions unique. Here we still use the run function to compare. For the following code to do the same thing. Their difference is the use of a with (T) function, and the other is the use of T.run function.

with(webView.settings){
    javaScriptEnabled = true
    databaseEnabled = true
}

webView.settings.run { 
    javaScriptEnabled = true
    databaseEnabled = true
}

But we think the use of which would be better? Now suppose a scenario that webView.settings may be null. That we have to look again at the code below.

with(webView.settings){
    javaScriptEnabled = true
    databaseEnabled = true
}

webView.settings?.run { 
    javaScriptEnabled = true
    databaseEnabled = true
}

Since it is so obvious, of course, it is T.run method will be better, because we can check for null before using these functions.

For there is also with a return value, it also returns the last object in the scope among.

Recipient of this scope and it

In these extension functions which, they can call directly to the object or objects with the arguments passed. In this five receivers spread function in their scope could be this or it. So let's compare T.run and T.let function. These two functions are also very similar.

stringVariable?.run {
    println("字符串的长度为$length")
}

stringVariable?.let {
    println("字符串的长度为 ${it.length}")
}

In these two pieces of code that can be clearly seen. StringVariable objects acquired by the T.run this function, and it is taken out by an object in T.let stringVariable function. Of course, we can rename it. If we do not want to cover this outer scope, this time to use T.let will be more convenient. As for the recipient which is a function of this, the recipient of which is a function of it, in the back will be clearly reflected by a tree diagram.

The return type of the scope

They will return a value in the present scope. The last object run about in the above, with, T.run, T.let they are returned scope. Of course, they return a value that allows the recipient and the type of this object, or different from it. But not all functions are extended returns the last object scope. For example T.also function.

val original = "abc"

original.let {
    println("The original String is $it") // "abc"
    it.reversed() 
}.let {
    println("The reverse String is $it") // "cba"
    it.length  
}.let {
    println("The length of the String is $it") // 3
}


original.also {
    println("The original String is $it") // "abc"
    it.reversed() 
}.also {
    println("The reverse String is ${it}") // "abc"
    it.length  
}.also {
    println("The length of the String is ${it}") // "abc"
}

From the above it can be seen T.let two codes and makes the return value T.also different. T.let returns the scope of the last object, its type and value can be changed. But how many times it is T.also original original object returned regardless of the call.

For T.let and T.also are able to operate the chain, we now look T.let combination of chained calls and T.also look at the application in actual scene.

//原始函数
fun makeDir(path: String): File  {
    val result = File(path)
    result.mkdirs()
    return result
}

//通过let和also的链式调用改进后的函数
fun makeDir(path: String) = path.let{ File(it) }.also{ it.mkdirs() }

Characteristics spread function

In addition to T.apply so far not used to the outside, according to the above usage, we can sum up these three characteristics extension functions.

  • They have their own scope
  • Recipient thereof or scope of this it is
  • They have a return value, returns the last object (this) or the caller itself (itself)

Thus conceivable for T.apply nothing more than these three characteristics. For the recipient T.apply its scope is this, the caller and the return of T. Thus, T.apply which a scene can be used to create a Fragment, code as follows:

// 使用普通的方法创建一个Fragment
fun createInstance(args: Bundle) : MyFragment {
    val fragment = MyFragment()
    fragment.arguments = args
    return fragment
}

// 通过apply来改善原有的方法创建一个Fragment
fun createInstance(args: Bundle) 
              = MyFragment().apply { arguments = args }

We can also call creates an Intent by T.apply chain:

// 普通创建Intent方法
fun createIntent(intentData: String, intentAction: String): Intent {
    val intent = Intent()
    intent.action = intentAction
    intent.data=Uri.parse(intentData)
    return intent
}

// 通过apply函数的链式调用创建Intent
fun createIntent(intentData: String, intentAction: String) =
        Intent().apply { action = intentAction }
                .apply { data = Uri.parse(intentData) }

How to choose

Here we look at the chart by a tree in front of the difference between five-spread function, use, and how to select the spread function (picture from among reference) 

è¿éåå¾çæè¿ °
Summarized
here to do some summary, we can see their characteristics among these five spread function is also very simple, nothing more than the recipient and return values are different. For with, T.run, T.apply recipient is this, and the recipients are T.let and T.also IT; for with, T.run, T.let return value is the last scoped object (this) while T.apply and T.also return value is the caller itself (itself).
--------------------- 
Author: No small mouth fool 
Source: CSDN 
Original: https: //blog.csdn.net/ljd2038/article/details/79576091 

Guess you like

Origin blog.csdn.net/qq_27981847/article/details/91435799