Kotlin Learning - Standard functions let, with, run, apply, also in Kotlin

Kotlin standard functions:

Standard function let

fun main() {
    
    
    val student = Student("lucky", 19);
    study(student)
}

fun study(student: Student?) {
    
    
    study?.doHomework()
    study?.readBooks()
}

In the Kotlin learning - nullable system type , if the input parameter is nullable, it needs to be added every time the object function is called in the function ?., and the code writing is too cumbersome. At this time, you can combine ?.operators and letfunctions to optimize the code, as shown below:

fun main() {
    
    
    val student = Student("lucky", 19);
    study(student)
}

fun study(student: Student?) {
    
    
    student?.let {
    
     s ->
        s.doHomework()
        s.readBooks()
    }
}

?.The operator means to do nothing when the object is empty, and to call letthe function when the object is not empty. When I was doing lamda expression optimization before ( Kotlin learning - collection ): When there is only one parameter in the parameter list of the Lambda expression, it is not necessary to declare the parameter name, but the it keyword can be used instead, so the above code can be optimized Down:

fun main() {
    
    
    val student = Student("lucky", 19);
    study(student)
}

fun study(student: Student?) {
    
    
    student?.let {
    
    
        it.doHomework()
        it.readBooks()
    }
}

letIn addition to helping us simplify the non-null judgment, multi-threading can also control the null judgment of global variables.

var student: Student? = null

fun study() {
    
    
    if (student !=null){
    
    
        student.doHomework()
        student.readBooks()
    }
}

The above code will compile and report an error because the value of the global variable may be modified by other threads at any time. Even if the null judgment is performed, there is still no guarantee that the variable ifin the statement studenthas no risk of null pointer. Use letthe function to modify:

var student: Student? = null

fun study() {
    
    
    student?.let {
    
    
		it.doHomework()
		it.readBooks()
    }        
}

After the error disappears and it is judged that the variable is not empty, execute the statement in let. let can ensure that the variable is not empty studentduring the execution of the lambda statement .student

Summary: letIt can help us simplify the non-null judgment, and it can also control the null judgment of global variables in multi-threading.

standard function with

fun main() {
    
    
    val fruits = listOf("apple", "banana", "pear")
    println(fruitPrint(fruits))
}

There is a list of fruits above, and the requirement is to splice them together in a fixed format. The usual implementation method is as follows:

fun fruitPrint(fruits: List<String>): String {
    
    
    val fruitPrint = StringBuilder();
    fruitPrint.append("My favorite fruits are : \n")
    
    for (f in fruits) {
    
    
        fruitPrint.append(f).append("\n")
    }
    
    fruitPrint.append("----- end -----")
    return fruitPrint.toString()
}

//打印结果
My favorite fruits are : 
apple
banana
pear
----- end -----

The object is called multiple times in a row where the string is spliced StringBuilder. For this scenario, we can use withfunctions to make the code more streamlined.

fun fruitPrint(fruits: List<String>): String {
    
    
   return with(StringBuilder()) {
    
    
        append("My favorite fruits are : \n")
        for (f in fruits) {
    
    
            append(f).append("\n")
        }
        append("----- end -----")
        toString()
    }
}

If withan object is passed in as the first parameter of the function StringBuilder, the context of the entire Lambda expression will be this StringBuilderobject. So we can directly call append()and toString()method in Lambda expression. The last line of code in the lambda expression is withreturned as the function's return value.

Summary: When frequent operations on the same object are required, withfunctions can be used to simplify the code.

standard function run

runThe usage of functions withis very similar to functions, but runfunctions are usually not called directly, but are called on the basis of an object. And withthere are two input parameters, runonly one Lambda expression input parameter.

Likewise, the last line of code in the lambda expression of withand is returned as the return value.run

The above example can be runrewritten as a function:

fun fruitPrint(fruits: List<String>): String {
    
    
   return StringBuilder().run {
    
    
        append("My favorite fruits are : \n")
        for (f in fruits) {
    
    
            append(f).append("\n")
        }
        append("----- end -----")
        toString()
    }
}

standard function apply

applyFunctions runare similar to functions, they must be called on an object, and only receive a Lambda parameter, and the context of the calling object will also be provided in the Lambda expression, but the apply function cannot specify the return value, but will automatically return the calling object itself.

fun fruitPrint(fruits: List<String>): String {
    
    
     val sb = StringBuilder().apply {
    
    
        append("My favorite fruits are : \n")
        for (f in fruits) {
    
    
            append(f).append("\n")
        }
        append("----- end -----")       
    }
    return sb.toString()
}

Since applythe function cannot specify the return value, it can only return the calling object itself, so it cannot be returned directly. Our return value declares the String type, so it needs to be converted.

Let's look at the usage in Android:

val intent = Intent(this,MainActivity::class.java).apply {
    
    
	putExtra("data1","data1")
	putExtra("data2",2)
	putExtra("data3",true)
}
startActivity(intent)

When starting MainActivity, you can go to Intentthe parameters contained in the configuration.

standard function also

The usage of also is similar to that of apply, see an example:

fun studentInfoCheck(s: Student) {
    
    
    s.also {
    
     it.name = "Lucky" }
    println(s.name)
}

Used internally itto refer to the context, a series of operations can be performed on the object. The return value applycan only return the calling object itself.

Differences in Standard Functions

Are you confused by learning here? Let’s compare the differences of the next few functions and it will look clearer.

standard function internal context return value
let it The last line of code in the let block
with this (can be omitted) The last line of code in the let block
run this (can be omitted) The last line of code in the let block
apply this (can be omitted) call the object itself
also it call the object itself

The difference between with & run

From the above table, the internal context and return value withof and runare the same, so what is the difference between the two?

  • withThere are two input parameters, runonly one Lambda expression input parameter;
  • Air safety judgment methods are different;

For the second point, let's take a look at the case:

fun printStudentInfo() {
    
    
	val s: Student? = null
	with(s) {
    
    
	    this?.name = "Tom"
	    this?.age = 4
	}
	print(s)
}

The above is to use withthe empty judgment. When using it, you need to judge the non-empty again every time, change runit to try

fun printStudentInfo() {
    
    
	val s: Student? = null
    s?.run {
    
    
        name = "Tom"
        age = 4
    }
	print(s)
}

First of all, runthe function call omits thisthe reference, and the empty security check is carried out in the outer layer, and only when it is non-empty can it enter the function block to operate Student. In comparison with, runfunctions are simpler, and null safety checks are less withfrequent.

Reference article
Differences between let, run, with, apply and also in Kotlin

Guess you like

Origin blog.csdn.net/kongqwesd12/article/details/131293825