🎯 When Expression
🎯 Mục tiêu: Nắm vững
when- công cụ pattern matching mạnh mẽ của Kotlin, thay thế cho switch-case và if-else phức tạp.
💡 Khái niệm
Phần tiêu đề “💡 Khái niệm”when là phiên bản nâng cấp của switch trong Java/C, nhưng mạnh mẽ hơn nhiều:
- Có thể match nhiều loại điều kiện
- Có thể dùng như expression (trả về giá trị)
- Không cần
break - Hỗ trợ smart cast
val x = 2
when (x) { 1 -> println("Một") 2 -> println("Hai") 3 -> println("Ba") else -> println("Khác")}📝 Cú pháp cơ bản
Phần tiêu đề “📝 Cú pháp cơ bản”When với giá trị cụ thể
Phần tiêu đề “When với giá trị cụ thể”val day = 3
val dayName = when (day) { 1 -> "Thứ Hai" 2 -> "Thứ Ba" 3 -> "Thứ Tư" 4 -> "Thứ Năm" 5 -> "Thứ Sáu" 6 -> "Thứ Bảy" 7 -> "Chủ Nhật" else -> "Không hợp lệ"}
println(dayName) // Thứ TưNhiều giá trị trong một branch
Phần tiêu đề “Nhiều giá trị trong một branch”val char = 'a'
val type = when (char) { 'a', 'e', 'i', 'o', 'u' -> "Nguyên âm" in 'a'..'z' -> "Phụ âm" in 'A'..'Z' -> "Chữ hoa" else -> "Khác"}When với ranges
Phần tiêu đề “When với ranges”val score = 85
val grade = when (score) { in 90..100 -> "A" in 80 until 90 -> "B" in 70 until 80 -> "C" in 60 until 70 -> "D" in 0 until 60 -> "F" else -> "Invalid"}⭐ When as Expression
Phần tiêu đề “⭐ When as Expression”val x = 3
val result = when (x) { 1 -> "One" 2 -> "Two" else -> "Many"}
// Với blockval description = when (x) { 1 -> { println("X is one") "Single" } 2 -> { println("X is two") "Double" } else -> { println("X is something else") "Multiple" }}🔍 When không có argument
Phần tiêu đề “🔍 When không có argument”Khi không có argument, when hoạt động như chuỗi if-else:
val age = 25val hasLicense = true
val canDrive = when { age < 18 -> "Chưa đủ tuổi" !hasLicense -> "Chưa có bằng lái" else -> "Được lái xe"}So sánh với if-else
Phần tiêu đề “So sánh với if-else”// if-elseval result = if (x > 0) { "Positive"} else if (x < 0) { "Negative"} else { "Zero"}
// when (rõ ràng hơn)val result = when { x > 0 -> "Positive" x < 0 -> "Negative" else -> "Zero"}🎯 When với Type Checking (is)
Phần tiêu đề “🎯 When với Type Checking (is)”fun describe(obj: Any): String = when (obj) { is Int -> "Integer: ${obj * 2}" // Smart cast! is String -> "String length: ${obj.length}" is Boolean -> if (obj) "True" else "False" is List<*> -> "List of ${obj.size} items" else -> "Unknown: ${obj::class.simpleName}"}
fun main() { println(describe(42)) // Integer: 84 println(describe("Hello")) // String length: 5 println(describe(true)) // True println(describe(listOf(1,2))) // List of 2 items}🔒 Exhaustive When với Sealed Class & Enum
Phần tiêu đề “🔒 Exhaustive When với Sealed Class & Enum”Enum - không cần else
Phần tiêu đề “Enum - không cần else”enum class Direction { NORTH, SOUTH, EAST, WEST }
fun move(direction: Direction): String = when (direction) { Direction.NORTH -> "Đi lên" Direction.SOUTH -> "Đi xuống" Direction.EAST -> "Đi phải" Direction.WEST -> "Đi trái" // Không cần else vì đã cover hết}Sealed class - không cần else
Phần tiêu đề “Sealed class - không cần else”sealed class Result { data class Success(val data: String) : Result() data class Error(val message: String) : Result() object Loading : Result()}
fun handleResult(result: Result): String = when (result) { is Result.Success -> "Data: ${result.data}" is Result.Error -> "Error: ${result.message}" Result.Loading -> "Loading..." // Không cần else!}🛠️ Thực hành
Phần tiêu đề “🛠️ Thực hành”Bài tập 1: Máy tính đơn giản
fun main() { val a = 10 val b = 3 val operator = "/"
// TODO: Tính kết quả dựa trên operator}Lời giải:
fun main() { val a = 10.0 val b = 3.0 val operator = "/"
val result = when (operator) { "+" -> a + b "-" -> a - b "*" -> a * b "/" -> if (b != 0.0) a / b else Double.NaN "%" -> a % b else -> Double.NaN }
println("$a $operator $b = $result")}Bài tập 2: Phân loại BMI
fun main() { val bmi = 23.5
// TODO: Phân loại theo BMI: // < 18.5: Thiếu cân // 18.5-24.9: Bình thường // 25-29.9: Thừa cân // >= 30: Béo phì}Lời giải:
fun main() { val bmi = 23.5
val category = when { bmi < 18.5 -> "Thiếu cân" bmi < 25.0 -> "Bình thường" bmi < 30.0 -> "Thừa cân" else -> "Béo phì" }
println("BMI: $bmi → $category")}Bài tập 3: Mô tả kiểu dữ liệu
fun main() { val items = listOf(42, "Hello", 3.14, true, null, listOf(1, 2))
// TODO: In mô tả cho mỗi item}Lời giải:
fun main() { val items: List<Any?> = listOf(42, "Hello", 3.14, true, null, listOf(1, 2))
for (item in items) { val description = when (item) { null -> "Null value" is Int -> "Integer: $item (doubled: ${item * 2})" is String -> "String: \"$item\" (length: ${item.length})" is Double -> "Double: ${"%.2f".format(item)}" is Boolean -> "Boolean: ${if (item) "Yes" else "No"}" is List<*> -> "List with ${item.size} elements" else -> "Unknown type" } println(description) }}📱 Trong Android
Phần tiêu đề “📱 Trong Android”// Xử lý navigationwhen (menuItemId) { R.id.nav_home -> navController.navigate(R.id.homeFragment) R.id.nav_profile -> navController.navigate(R.id.profileFragment) R.id.nav_settings -> navController.navigate(R.id.settingsFragment)}
// Xử lý API responsewhen (response) { is NetworkResult.Success -> showData(response.data) is NetworkResult.Error -> showError(response.message) is NetworkResult.Loading -> showLoading()}
// View click handlingview.setOnClickListener { v -> when (v.id) { R.id.btnSubmit -> submitForm() R.id.btnCancel -> cancel() R.id.btnReset -> resetForm() }}⚠️ Lưu ý quan trọng
Phần tiêu đề “⚠️ Lưu ý quan trọng”✅ Checklist - Tự kiểm tra
Phần tiêu đề “✅ Checklist - Tự kiểm tra”Sau bài học này, bạn có thể:
- Sử dụng when với giá trị cụ thể
- Sử dụng when với ranges (
in 1..10) - Sử dụng when với type checking (
is) - Sử dụng when không có argument
- Hiểu exhaustive when với sealed class/enum
- Biết when luôn cần
elsekhi dùng làm expression (trừ sealed/enum)
Tiếp theo: Vòng lặp for