Scope Function ใน Kotlin [ Let, With, Run, Apply, Also ]

TopToppy
odds.team
Published in
2 min readMay 20, 2023
Photo by Louis Tsai on Unsplash

ทุกๆ Type ใน Kotlin จะถูกประกาศ extension function ที่กำหนดให้คุณสามารถเรียก execute code ภายใต้ context ของ object นั้นๆ ได้ โดยเมื่อคุณทำการเรียกใช้จะมีการกำหนด scope ชั่วคราว โดยคุณสามารถเข้าถึง object โดยไม่ต้องกำหนดชื่อ เราเรียก function ดังกล่าวว่า Scope Function โดยประกอบไปด้วย Let, With, Run, Apply, Also

Let

เรียกใช้เพื่อทำการ Invoke 1 function หรือมากกว่า โดย return result จะถูก chain กันต่อไปเรื่อย ๆ

val scopeFunction = mutableListOf("let", "with", "run", "apply", "also")
scopeFunction
.let{ println("let() called on $it") }

//let() called on [let, with, run, apply, also]

let ยังใช้เพื่อ check null ได้อีกด้วย โดยเมื่อ nullable type เรียกใช้ let หากพบว่าเป็น null จะทำให้ let ไม่ถูกเรียกใช้

val str: String? = "Scope Function"   

str?.let {
println("let() called on $it") // let() called on Scope Function
}

With

เรียกใช้เพื่อทำการส่ง object เข้ามาทำงานภายใต้ context โดยไม่มีการ return result หรือจะจำการทำงานได้ว่าว่า “ with this object do following ”

val scopeFunction = mutableListOf("let", "with", "run", "apply", "also")
with(scopeFunction) {
println("with() is called with argument $this")
println("It contains $size elements")
}

//run() is called with argument [let, with, run, apply, also]
//It contains 5 elements

Run

ลักษณะการทำงานคล้ายกับ with เพียงแต่เป็นการเรียกใช้ผ่าน dot notation และ run สามารถเรียกแบบ non-extension function ได้

val scopeFunction = mutableListOf("let", "with", "run", "apply")
scopeFunction.run {
println("run() is called with argument $this")
println("It contains $size elements")
add("also")
println("run() is called with argument $this")
println("It contains $size elements")
}

//run() is called with argument [let, with, run, apply]
//It contains 4 elements
//run() is called with argument [let, with, run, apply, also]
//It contains 5 elements

run ยังสามารถเรียกแบบ non-extension function ได้ด้วย ตัวอย่างใช้เพื่อทำการสร้าง regex ก่อนนำไปใช้

val hexNumberRegex = run {
val digits = "0-9"
val hexDigits = "A-Fa-f"
val sign = "+-"
Regex("[$sign]?[$digits$hexDigits]+")
}

for (match in hexNumberRegex.findAll("+123 -FFFF !%*& 88 XYZ")) {
println(match.value)
}

Apply

เรียกใช้เพื่อปรับปลี่ยน object ตัวเดิมตามค่าที่กำหนดและ return object ตัวเดิม มักถูกใช้ในการทำ object configuration หรือจะจำง่ายว่า “ Apply the following assignment to this object ”

data class Person(var name: String, var tutorial : String)
var person = Person("Anupam", "Java") // Person("Anupam", "Java")

person.apply { this.tutorial = "Kotlin" } // Person("Anupam", "Kotlin")

Also

เรียกใช้เมื่อต้องการใช้งาน object และ return object ตัวเดิมออกมาก โดยเรียกเป็นประโยคได้ว่า “ and also do this following with the object ”

val pets = mutableListOf("cat", "dog")
pets
.also { println("pets: $it") } // pets: [cat, dog]
.also { it.add("bird") }
.also { println("pets: $it") } // pets: [cat, dog, bird]

ทั้ง 5 อย่างสามารถนำไปประยุกต์ใช้ได้หลากหลาย หวังว่าจะเป็นประโยชน์กับหลายๆคนได้บ้างครับ

--

--