Skip to Content
Kotlin📘 Ngôn ngữ Kotlin🔍 Scope Functions

Scope Functions trong Kotlin

🎯 Mục tiêu: Nắm vững 5 scope functions: let, run, with, apply, also - công cụ viết code Kotlin idiomatic.


💡 Tổng quan

Scope functions tạo scope tạm thời để thao tác với object. Chúng khác nhau ở:

  1. Cách tham chiếu object: this (context object) hoặc it (lambda argument)
  2. Giá trị trả về: Object gốc hoặc kết quả lambda
FunctionReferenceReturnsUse case
letitLambda resultNull checks, scoping
runthisLambda resultObject config + compute
withthisLambda resultGroup operations
applythisObjectObject configuration
alsoitObjectSide effects

📝 let

Reference: it | Returns: Lambda result

// Null check val name: String? = "Kotlin" name?.let { println("Name length: ${it.length}") } // Scoping transformation val result = "hello".let { println("Original: $it") it.uppercase() } println(result) // HELLO

Use case: Chain transformations

val numbers = mutableListOf("one", "two", "three") val resultList = numbers.map { it.length }.filter { it > 3 } println(resultList) // Hoặc dùng let cho clarity numbers .map { it.length } .filter { it > 3 } .let { println(it) }

🔄 run

Reference: this | Returns: Lambda result

val result = "hello".run { println("Length: $length") // this.length uppercase() // return value } println(result) // HELLO

Use case: Object config + compute result

val service = NetworkService().run { port = 8080 timeout = 30000 connect() // Returns connection result }

run không có receiver

val hexString = run { val red = 255 val green = 128 val blue = 0 "#${red.toString(16)}${green.toString(16)}${blue.toString(16)}" }

🔗 with

Reference: this | Returns: Lambda result

val numbers = mutableListOf("one", "two", "three") with(numbers) { println("List: $this") println("Size: $size") println("First: ${first()}") }

Use case: Group operations on object

val config = with(Configuration()) { host = "localhost" port = 8080 timeout = 5000 this // Return config }

[!NOTE] with không phải extension function, syntax: with(object) { }


🛠️ apply

Reference: this | Returns: Object itself

val person = Person().apply { name = "Alice" age = 25 city = "Hanoi" } // person đã được config và trả về

Use case: Builder pattern, object initialization

val intent = Intent(this, MainActivity::class.java).apply { putExtra("USER_ID", 123) putExtra("USER_NAME", "Alice") addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } val textView = TextView(context).apply { text = "Hello" textSize = 16f setTextColor(Color.BLACK) gravity = Gravity.CENTER }

👀 also

Reference: it | Returns: Object itself

val numbers = mutableListOf("one", "two", "three") numbers .also { println("Before: $it") } .add("four") .also { println("Add successful") }

Use case: Logging, debugging, side effects

val user = createUser() .also { println("Created user: ${it.name}") } .also { validateUser(it) } .also { saveToDatabase(it) }

🎯 Chọn Scope Function phù hợp

Quy tắc đơn giản

Mục đíchDùng
Null check & transformlet
Object initializationapply
Side effects/loggingalso
Run code block, get resultrun
Group operations on objectwith

🛠️ Thực hành

Bài tập 1: Refactor code với scope functions

// Before fun createUser(): User { val user = User() user.name = "Alice" user.age = 25 user.email = "[email protected]" println("Created user: $user") return user } // TODO: Refactor dùng apply và also

Lời giải:

fun createUser() = User().apply { name = "Alice" age = 25 email = "[email protected]" }.also { println("Created user: $it") }

Bài tập 2: Null-safe operation chain

fun main() { val user: User? = findUser(123) // TODO: Nếu user exists, validate và save }

Lời giải:

fun main() { val user: User? = findUser(123) user?.let { u -> validateUser(u) }?.run { saveToDatabase(this) sendWelcomeEmail(this.email) "User saved successfully" } ?: "User not found" }

Bài tập 3: Builder pattern

fun main() { // TODO: Tạo request với apply }

Lời giải:

val request = HttpRequest().apply { url = "https://api.example.com/users" method = "POST" headers["Content-Type"] = "application/json" headers["Authorization"] = "Bearer token123" body = """{"name": "Alice", "age": 25}""" }.also { println("Sending request to ${it.url}") }

📱 Trong Android

// View configuration with apply val button = Button(context).apply { text = "Click Me" setTextColor(Color.WHITE) setBackgroundColor(Color.BLUE) setOnClickListener { handleClick() } } // Intent with apply startActivity(Intent(this, DetailActivity::class.java).apply { putExtra("ITEM_ID", item.id) putExtra("ITEM_NAME", item.name) }) // Null-safe with let user?.let { currentUser -> binding.nameText.text = currentUser.name binding.emailText.text = currentUser.email binding.avatarImage.load(currentUser.avatarUrl) } // Logging with also viewModel.loadData() .also { Log.d(TAG, "Data loaded: ${it.size} items") } .also { analytics.trackDataLoad(it.size) }

⚠️ Lưu ý quan trọng

[!WARNING] Không lồng quá nhiều scope functions:

// ❌ Khó đọc obj.let { it.run { this.apply { also { } } } } // ✅ Tách thành steps rõ ràng val processed = obj.let { transform(it) } processed.apply { configure() }

[!TIP] Khi this conflicts, dùng it version:

class MyClass { fun process() { // this đã là MyClass someObject.also { obj -> // Dùng also thay vì apply obj.property = this.value } } }

✅ Checklist - Tự kiểm tra

Sau bài học này, bạn có thể:

  • Biết 5 scope functions: let, run, with, apply, also
  • Phân biệt this vs it reference
  • Phân biệt return object vs return lambda result
  • Chọn đúng scope function cho use case
  • Sử dụng let cho null check
  • Sử dụng apply cho object initialization

Tiếp theo: Collections - List

Last updated on