Viết các điều kiện trong Kotlin

1. Trước khi bắt đầu

Điều kiện là một trong những cơ sở quan trọng nhất khi lập trình. Điều kiện là các lệnh bằng ngôn ngữ lập trình giúp xử lý quyết định. Trong điều kiện, mã có tính động, nghĩa là mã có thể hoạt động khác dựa trên điều kiện khác nhau.

Lớp học lập trình này hướng dẫn bạn cách sử dụng câu lệnh và biểu thức if/elsewhen để viết các điều kiện trong Kotlin.

Điều kiện tiên quyết

  • Kiến thức cơ bản về lập trình Kotlin, bao gồm các biến cũng như các hàm println()main()

Kiến thức bạn sẽ học được

  • Cách viết biểu thức boolean.
  • Cách viết câu lệnh if/else.
  • Cách viết câu lệnh when.
  • Cách viết biểu thức if/else.
  • Cách viết biểu thức when.
  • Cách sử dụng dấu phẩy để xác định hành vi chung cho nhiều nhánh trong when điều kiện.
  • Cách sử dụng dải ô in để xác định hành vi chung cho một loạt các nhánh trong when điều kiện.
  • Cách dùng từ khóa is để viết when câu lệnh có điều kiện.

Bạn cần có

  • Một trình duyệt web có quyền truy cập vào Kotlin Playground

2. Sử dụng câu lệnh if/else để thể hiện điều kiện

Trong cuộc sống, chúng ta thường xử lý sự việc khác nhau dựa trên tình huống mà mình gặp phải. Ví dụ: nếu thời tiết lạnh thì bạn mặc áo khoác, và bạn sẽ không mặc thế khi thời tiết ấm áp.

Sơ đồ quy trình mô tả một quyết định được đưa ra khi thời tiết lạnh. Bạn có thể sử dụng mũi tên yes (có) trỏ đến thông báo "Mặc áo khoác" và mũi tên no (không) chỉ vào thông báo "Không mặc áo khoác".

Đưa ra quyết định cũng là một khái niệm cơ bản trong chương trình. Bạn viết hướng dẫn về cách xử lý của chương trình trong một tình huống nhất định để chương trình có thể hành động hoặc phản ứng phù hợp khi tình huống đó xảy ra. Trong Kotlin, khi muốn chương trình của mình thực hiện nhiều thao tác dựa trên một điều kiện, bạn có thể dùng câu lệnh if/else. Trong phần tiếp theo, bạn hãy viết một câu lệnh if.

Viết các điều kiện if bằng biểu thức boolean

Hãy tưởng tượng bạn đang xây dựng một chương trình để trình điều khiển biết chúng nên làm gì khi gặp đèn giao thông. Tập trung vào điều kiện đầu tiên: đèn giao thông màu đỏ. Bạn sẽ làm gì với đèn giao thông màu đỏ? Dừng

Sơ đồ quy trình mô tả một quyết định được đưa ra khi gặp đèn giao thông có màu đỏ. Mũi tên yes (có) trỏ đến thông báo "Dừng"!.

Trong Kotlin, bạn có thể biểu thị điều kiện này bằng một câu lệnh if. Hãy xem cấu trúc của câu lệnh if:

Sơ đồ mô tả câu lệnh if với từ khóa if theo sau là một cặp dấu ngoặc đơn có khối condition (điều kiện) bên trong. Sau đó, bạn sẽ thấy một cặp dấu ngoặc nhọn có khối body (thân) bên trong. Khối điều kiện được làm nổi bật.

Để sử dụng câu lệnh if, bạn cần sử dụng từ khóa if theo sau là điều kiện bạn muốn đánh giá. Bạn cần thể hiện điều kiện bằng biểu thức boolean. Biểu thức kết hợp các giá trị, biến và toán tử để trả về một giá trị. Biểu thức boolean trả về một giá trị boolean.

Trước đây, bạn đã tìm hiểu về toán tử gán, chẳng hạn như:

val number = 1

Toán tử gán = sẽ chuyển cho biến number một giá trị 1.

Ngược lại, các biểu thức boolean được tạo bằng toán tử so sánh. Các toán tử này sẽ so sánh giá trị hoặc biến trên cả hai vế của phương trình. Hãy tìm hiểu về toán tử so sánh.

1 == 1

Toán tử so sánh == so sánh các giá trị với nhau. Bạn nghĩ biểu thức này trả về giá trị boolean nào?

Tìm giá trị boolean của biểu thức này:

  1. Dùng Kotlin Playground để chạy mã.
  2. Trong phần thân hàm, hãy thêm hàm println(), sau đó truyền biểu thức 1 == 1 làm đối số:
fun main() {
    println(1 == 1)
}
  1. Chạy chương trình rồi xem kết quả:
true

Giá trị 1 đầu tiên bằng giá trị 1 thứ hai, do đó biểu thức boolean trả về một giá trị true, là giá trị boolean.

Dùng thử

Ngoài toán tử so sánh ==, bạn có thể dùng các toán tử so sánh khác để tạo biểu thức boolean:

  • Ít hơn: <
  • Lớn hơn: >
  • Ít hơn hoặc bằng: <=
  • Lớn hơn hoặc bằng: >=
  • Không bằng: !=

Thực hành sử dụng toán tử so sánh với biểu thức đơn giản:

  1. Trong đối số, hãy thay thế toán tử so sánh == bằng toán tử so sánh <:
fun main() {
    println(1 < 1)
}
  1. Chạy chương trình rồi xem kết quả:

Kết quả trả về giá trị false vì giá trị 1 đầu tiên không nhỏ hơn giá trị 1 thứ hai.

false
  1. Lặp lại 2 bước đầu tiên với các toán tử so sánh và số khác.

Viết một câu lệnh if đơn giản

Bây giờ, bạn đã thấy một vài ví dụ về cách viết biểu thức boolean, bạn có thể viết câu lệnh if đầu tiên. Cú pháp cho câu lệnh if như sau:

Sơ đồ mô tả câu lệnh if với từ khóa if theo sau là một cặp dấu ngoặc đơn có khối condition (điều kiện) bên trong. Sau đó, bạn sẽ thấy một cặp dấu ngoặc nhọn có khối body (thân) bên trong. Phần thân được làm nổi bật.

Câu lệnh if bắt đầu bằng từ khóa if theo sau là điều kiện, điều kiện này là biểu thức boolean bên trong dấu ngoặc đơn và một tập hợp dấu ngoặc nhọn. Phần thân là một chuỗi câu lệnh hoặc biểu thức mà bạn đặt bên trong một cặp dấu ngoặc nhọn sau điều kiện. Những câu lệnh hoặc biểu thức này chỉ thực thi khi điều kiện được đáp ứng. Nói cách khác, câu lệnh trong dấu ngoặc nhọn chỉ thực thi khi biểu thức boolean trong nhánh if trả về giá trị true.

Viết câu lệnh if cho điều kiện đèn giao thông màu đỏ:

  1. Bên trong hàm main(), hãy tạo một biến trafficLightColor và chỉ định giá trị đó cho biến "Red":
fun main() {
    val trafficLightColor = "Red"
}
  1. Thêm câu lệnh if cho điều kiện đèn giao thông màu đỏ, sau đó truyền biểu thức trafficLightColor == "Red":
fun main() {
    val trafficLightColor = "Red"

    if (trafficLightColor == "Red") {

    }
}
  1. Trong phần thân của câu lệnh if, hãy thêm một hàm println(), sau đó truyền vào đối số "Stop":
fun main() {
    val trafficLightColor = "Red"

    if (trafficLightColor == "Red") {
        println("Stop")
    }
}
  1. Chạy chương trình rồi xem kết quả:
Stop

Biểu thức trafficLightColor == "Red" trả về giá trị true, do đó câu lệnh println("Stop") sẽ được thực thi, in ra thông báo Stop.

Sơ đồ làm nổi bật câu lệnh if của trafficLightColor == "Đỏ" dưới dạng biểu thức và điều kiện Boolean. Ở dòng tiếp theo, phần thân println("Stop") sẽ được lưu ý với nội dung chỉ thực thi khi biểu thức Boolean là true.

Thêm một nhánh else

Giờ đây, bạn có thể mở rộng chương trình để ra tín hiệu cho trình điều khiển đi khi đèn giao thông không có màu đỏ.

Sơ đồ quy trình mô tả một quyết định được đưa ra khi gặp đèn giao thông có màu đỏ. Mũi tên yes (có) trỏ đến thông báo "Dừng"!. Mũi tên no (không) trỏ đến thông báo "Tiếp tục"!.

Bạn cần thêm một nhánh else để tạo câu lệnh if/else. Nhánh là một phần mã chưa hoàn chỉnh mà bạn có thể tham gia để tạo thành các câu lệnh hoặc biểu thức. Nhánh else cần phải theo nhánh if.

Sơ đồ mô tả câu lệnh if/else với từ khóa if, theo sau là dấu ngoặc đơn có khối condition (điều kiện) bên trong. Tiếp theo, bạn sẽ thấy một cặp dấu ngoặc nhọn với khối body 1 (thân 1) bên trong, theo sau có từ khóa else (khác) đứng trước dấu. ngoặc nhọn. Theo sau là một cặp dấu ngoặc nhọn với khối body 2 (thân 2) bên trong.

Sau dấu ngoặc nhọn đóng của câu lệnh if, bạn phải thêm từ khóa else theo sau là một cặp dấu ngoặc nhọn. Bên trong dấu ngoặc nhọn của câu lệnh else, bạn có thể thêm một phần thân thứ hai chỉ thực thi khi điều kiện trong nhánh if là false.

Thêm nhánh else vào lập trình của bạn:

  1. Sau dấu ngoặc nhọn đóng của câu lệnh if, hãy thêm từ khóa else, theo sau là một cặp dấu ngoặc nhọn khác:
fun main() {
    val trafficLightColor = "Red"

    if (trafficLightColor == "Red") {
        println("Stop")
    } else {

    }
}
  1. Bên trong dấu ngoặc nhọn của từ khóa else, hãy thêm một hàm println() rồi chuyển đối số "Go" cho hàm này:
fun main() {
    val trafficLightColor = "Red"

    if (trafficLightColor == "Red") {
        println("Stop")
    } else {
        println("Go")
    }
}
  1. Chạy chương trình này rồi xem kết quả:
Stop

Chương trình này vẫn hoạt động giống như trước khi bạn thêm nhánh else, nhưng không in thông báo Go.

  1. Chỉ định lại biến trafficLightColor cho giá trị Green vì bạn muốn trình điều khiển đi khi gặp màu xanh lục:
fun main() {
    val trafficLightColor = "Green"

    if (trafficLightColor == "Red") {
        println("Stop")
    } else {
        println("Go")
    }
}
  1. Chạy chương trình này rồi xem kết quả:
Go

Như bạn có thể thấy, hiện tại chương trình đã in thông báo Go thay vì thông báo Stop.

Sơ đồ làm nổi câu lệnh if/else với điều kiện trafficLight == "Đỏ" được ghi chú dưới dạng biểu thức Boolean. Phần thân println("Stop") sẽ được lưu ý với nội dung chỉ thực thi khi biểu thức Boolean là true. Bên trong mệnh đề khác, câu lệnh println("Go") được lưu ý với nội dung chỉ được thực thi khi biểu thức Boolean là false.

Bạn đã chỉ định lại biến trafficLightColor thành giá trị "Green", do đó biểu thức trafficLightColor == "Red" được đánh giá trong nhánh if sẽ trả về giá trị false vì giá trị "Green" không bằng với giá trị "Red".

Kết quả là, chương trình này sẽ bỏ qua tất cả câu lệnh trong nhánh if và thay vào đó thực thi tất cả câu lệnh trong nhánh else. Điều này có nghĩa là hàm println("Go") được thực thi nhưng hàm println("Stop") thì khôngi.

Thêm một nhánh else if

Thông thường, đèn giao thông cũng có màu vàng để báo cho trình điều khiển tiến hành chậm lại. Bạn có thể mở rộng quy trình ra quyết định của chương trình để thể hiện việc này.

Sơ đồ quy trình mô tả một quyết định được đưa ra khi gặp đèn giao thông có màu đỏ. Mũi tên yes (có) trỏ đến thông báo "Dừng"!. Mũi tên no (không) trỏ đến việc thực hiện một quyết định khác khi đèn giao thông có màu vàng. Tại điểm quyết định đó, mũi tên yes (có) trỏ đến thông báo "Chậm lại" và mũi tên no (không) trỏ đến thông báo "Tiếp tục".

Bạn đã tìm hiểu cách viết các điều kiện phục vụ cho một điểm quyết định đơn lẻ bằng câu lệnh if/else có chứa if đơn lẻ và một nhánh else. Bạn làm gì để xử lý việc phân nhánh phức tạp hơn bằng nhiều điểm quyết định? Khi gặp các trường hợp có nhiều điểm quyết định, bạn cần tạo điều kiện với nhiều lớp điều kiện. Bạn có thể làm điều này khi thêm nhánh else if vào câu lệnh if/else.

Sau khi dấu ngoặc nhọn đóng của nhánh if, bạn cần thêm từ khóa else if. Bên trong dấu ngoặc đơn của từ khóa else if, bạn cần thêm một biểu thức boolean làm điều kiện cho nhánh else if, theo sau là phần thân bên trong một cặp dấu ngoặc nhọn. Phần thân chỉ được thực thi khi không thỏa mãn condition 1 (điều kiện 1), nhưng đáp ứng được condition 2 (điều kiện 2).

Sơ đồ mô tả câu lệnh if/else với từ khóa if, theo sau là dấu ngoặc đơn có khối condition 1 (điều kiện 1) bên trong. Sau đó, bạn sẽ thấy một cặp dấu ngoặc nhọn có khối body 1 (thân 1) bên trong.   Tiếp theo là từ khóa else if có dấu ngoặc đơn với khối condition 2 (điều kiện 2) bên trong. Tiếp theo, bạn sẽ thấy một dấu ngoặc nhọn có khối body 2 (thân 2) bên trong.  Tiếp theo là từ khóa else với một cặp dấu ngoặc nhọn với khối body 3 (thân 3) bên trong.

Nhánh else if luôn nằm sau nhánh if, nhưng trước nhánh else. Bạn có thể dùng nhiều nhánh else if trong một câu lệnh:

Sơ đồ cho thấy điều kiện if/else với nhiều nhánh else if giữa các nhánh if và else. Một nội dung được chú thích xung quanh nhánh else if cho biết có nhiều nhánh else if.

Câu lệnh if cũng có thể chứa nhánh if và các nhánh else if nhưng không có bất kỳ nhánh else nào:

Sơ đồ mô tả câu lệnh if/else với từ khóa if, theo sau là dấu ngoặc đơn có khối condition 1 (điều kiện 1) bên trong. Sau đó, bạn sẽ thấy một cặp dấu ngoặc nhọn có khối body 1 (thân 1) bên trong.   Tiếp theo là từ khóa else if có dấu ngoặc đơn với khối condition 2 (điều kiện 2) bên trong. Tiếp theo, bạn sẽ thấy một dấu ngoặc nhọn có khối body 2 (thân 2) bên trong.

Thêm nhánh else if vào lập trình của bạn:

  1. Sau dấu ngoặc nhọn đóng của câu lệnh if, hãy thêm một biểu thức else if (trafficLightColor == "Yellow"), theo sau là dấu ngoặc nhọn:
fun main() {
    val trafficLightColor = "Green"

    if (trafficLightColor == "Red") {
        println("Stop")
    } else if (trafficLightColor == "Yellow") {

    } else {
        println("Go")
    }
}
  1. Bên trong dấu ngoặc nhọn của nhánh else if, hãy thêm một câu lệnh println(), sau đó truyền đối số này vào chuỗi "Slow":
fun main() {
    val trafficLightColor = "Green"

    if (trafficLightColor == "Red") {
        println("Stop")
    } else if (trafficLightColor == "Yellow") {
        println("Slow")
    } else {
        println("Go")
    }
}
  1. Chỉ định lại biến trafficLightColor cho một giá trị chuỗi "Yellow":
fun main() {
    val trafficLightColor = "Yellow"

    if (trafficLightColor == "Red") {
        println("Stop")
    } else if (trafficLightColor == "Yellow") {
        println("Slow")
    } else {
        println("Go")
    }
}
  1. Chạy chương trình này rồi xem kết quả:
Slow

Chương trình lúc này sẽ in thông báo Slow thay vì thông báo Stop hoặc Go.

Sơ đồ làm nổi bật câu lệnh if/else với điều kiện trafficLight == "Đỏ" trong mệnh đề if được ghi chú dưới dạng biểu thức Boolean 1 và trafficLight == "Vàng" được ghi chú là biểu thức boolean 2. Phần thân println("stop") được lưu ý là chỉ thực thi khi biểu thức Boolean 1 là true. Phần thân println("slow") được lưu ý là chỉ được thực thi khi biểu thức Boolean 1 là false, nhưng biểu thức Boolean 2 là true. Phần thân println("go") được lưu ý là chỉ thực thi khi câu lệnh Boolean 1 và 2 là false.

Dưới đây là lý do tại sao chế độ này chỉ in thông báo Slow chứ không in các dòng khác:

  • Biến trafficLightColor được gán giá trị "Yellow".
  • Giá trị "Yellow" không bằng giá trị "Red", do đó biểu thức boolean của nhánh if (được biểu thị là 1 trong hình ảnh) trả về một giá trị false. Lập trình này sẽ bỏ qua mọi câu lệnh bên trong nhánh if và không in thông báo Stop.
  • Vì nhánh if tạo ra giá trị false nên chương trình sẽ tiếp tục đánh giá biểu thức boolean bên trong nhánh else if.
  • Giá trị "Yellow" bằng giá trị "Yellow", do đó biểu thức boolean của nhánh else if (được biểu thị là 2 trong hình ảnh) trả về một giá trị true. Lập trình này sẽ thực thi tất cả câu lệnh bên trong nhánh else if và in thông báo Slow.
  • Vì boolean expression của nhánh else if trả về giá trị true nên chương trình này sẽ bỏ qua phần còn lại của các nhánh. Theo đó, tất cả các câu lệnh trong nhánh else không được thực thi và lập trình sẽ không in thông báo Go.

Dùng thử

Bạn có nhận thấy lập trình hiện tại chứa lỗi không?

Trong Bài 1, bạn đã tìm hiểu về một loại lỗi gọi là lỗi biên dịch, trong đó Kotlin không thể biên dịch mã do lỗi cú pháp trong mã của bạn khiến lập trình không thể chạy. Trong bài này bạn sẽ gặp một loại lỗi khác được gọi là lỗi logic, trong đó chương trình này có thể chạy nhưng không tạo ra kết quả như dự định.

Giả sử bạn chỉ muốn trình điều khiển khởi chạy khi đèn giao thông có màu xanh lục. Điều gì sẽ xảy ra nếu đèn giao thông bị hỏng và tắt? Bạn muốn trình điều khiển chạy hay nhận cảnh báo rằng có gì đó không ổn?

Rất tiếc, trong lập trình hiện tại, nếu màu đèn giao thông là bất kỳ màu nào khác mà không phải là màu đỏ hoặc vàng thì trình điều khiển vẫn nên tiếp tục.

Khắc phục sự cố này:

  1. Chỉ định lại biến trafficLightColor cho giá trị "Black" để minh họa đèn giao thông đã tắt:
fun main() {
    val trafficLightColor = "Black"

    if (trafficLightColor == "Red") {
        println("Stop")
    } else if (trafficLightColor == "Yellow") {
        println("Slow")
    } else {
        println("Go")
    }
}
  1. Chạy chương trình này rồi xem kết quả:
Go

Lưu ý chương trình này sẽ in thông báo Go mặc dù biến trafficLightColor chưa được gán giá trị "Green". Bạn có thể sửa lập trình này để phản ánh đúng hành vi không?

Sơ đồ quy trình mô tả một quyết định được đưa ra khi gặp đèn giao thông có màu đỏ. Mũi tên yes (có) trỏ đến thông báo "Dừng"!. Mũi tên no (không) trỏ đến việc thực hiện một quyết định khác khi đèn giao thông có màu vàng. Tại điểm quyết định đó, mũi tên yes (có) trỏ đến thông báo "Chậm lại" và mũi tên no (không) trỏ đến việc thực hiện một quyết định khác khi màu đèn giao thông có màu xanh lục. Tại điểm quyết định đó, mũi tên yes (có) trỏ đến thông báo "Go" (tiếp tục) và mũi tên no (không) trỏ đến thông báo "Màu không hợp lệ".

Bạn cần phải sửa đổi để lập trình này có thể in:

  • Thông báo Go chỉ khi biến trafficLightColor được gán một giá trị "Green".
  • Thông báo Invalid traffic-light color khi biến trafficLightColor không được chỉ định giá trị "Red", "Yellow" hoặc "Green".

Chỉnh sửa nhánh else

nhánh else luôn nằm ở cuối câu lệnh if/else vì đó là nhánh chung. Hàm này sẽ tự động thực thi khi tất cả những điều kiện khác trong các nhánh trước không được đáp ứng. Do đó, nhánh else không phù hợp khi bạn chỉ muốn thực hiện một hành động khi đáp ứng một điều kiện cụ thể. Trong trường hợp đèn giao thông, bạn có thể sử dụng nhánh else if để chỉ định điều kiện cho đèn màu xanh lục.

Sử dụng nhánh else if để đánh giá điều kiện đèn giao thông màu xanh lục:

  1. Sau nhánh else if hiện tại, hãy thêm một nhánh else if (trafficLightColor == "Green") khác:
fun main() {
    val trafficLightColor = "Black"

    if (trafficLightColor == "Red") {
        println("Stop")
    } else if (trafficLightColor == "Yellow") {
        println("Slow")
    } else if (trafficLightColor == "Green") {
        println("Go")
    }
}
  1. Chạy chương trình này rồi xem kết quả.

Kết quả trống vì bạn không có nhánh else thực thi khi những điều kiện trước không được đáp ứng.

  1. Sau nhánh else if cuối cùng, hãy thêm nhánh else có câu lệnh println("Invalid traffic-light color") bên trong:
fun main() {
    val trafficLightColor = "Black"

    if (trafficLightColor == "Red") {
        println("Stop")
    } else if (trafficLightColor == "Yellow") {
        println("Slow")
    } else if (trafficLightColor == "Green") {
        println("Go")
    } else {
        println("Invalid traffic-light color")
    }

}
  1. Chạy chương trình này rồi xem kết quả:
Invalid traffic-light color
  1. Chỉ định một giá trị khác cho biến trafficLightColor ngoài "Red", "Yellow" hoặc "Green", rồi chạy lại chương trình.

Kết quả của chương trình là gì?

Bạn nên có một nhánh else if rõ ràng làm phương thức xác thực đầu vào cho màu xanh lục và một nhánh else để phát hiện các đầu vào không hợp lệ khác. Điều này đảm bảo trình điều khiển được chuyển hướng đến tiếp tục, chỉ khi đèn giao thông có màu xanh lục. Đối với các trường hợp khác, một thông báo rõ ràng được chuyển tiếp rằng đèn giao thông không hoạt động như mong đợi.

3. Sử dụng câu lệnh when cho nhiều nhánh

Lập trình trafficLightColor của bạn sẽ phức tạp hơn với nhiều điều kiện, còn được gọi là phân nhánh. Bạn có thể thắc mắc liệu mình có thể đơn giản hóa một lập trình có nhiều nhánh hơn nữa hay không.

Trong Kotlin, khi xử lý nhiều nhánh, bạn có thể dùng câu lệnh when thay cho câu lệnh if/else, vì câu đó khiến việc đọc dễ dàng hơn, ở đây là mức độ dễ đọc đối với người đọc, thường là các nhà phát triển. Điều quan trọng là bạn phải xem xét khả năng đọc khi viết mã, bởi vì có thể các nhà phát triển khác cần xem xét và sửa đổi mã của bạn trong suốt vòng đời của nó. Mã dễ đọc sẽ giúp các nhà phát triển có thể hiểu chính xác mã của bạn và không vô tình đưa lỗi vào mã đó.

Câu lệnh when được ưu tiên khi có nhiều hơn hai nhánh cần xem xét.

Sơ đồ cho thấy cấu trúc của câu lệnh when. Bắt đầu bằng từ khóa when, theo sau là một cặp dấu ngoặc nhọn có khối parameter (tham số) bên trong. Tiếp theo, bên trong một cặp dấu ngoặc nhọn có ba dòng khối. Bên trong mỗi dòng là khối conditon (điều kiện) theo sau là biểu tượng mũi tên cùng với khối body (thân). Lưu ý mỗi dòng khối được đánh giá theo tuần tự.

Câu lệnh when chấp nhận một giá trị đơn lẻ thông qua tham số. Theo đó giá trị này được đánh giá theo từng điều kiện. Sau đó, phần thân tương ứng đáp ứng điều kiện đầu tiên sẽ được thực thi. Mỗi điều kiện và thân đều được phân tách bằng mũi tên (->). Tương tự như câu lệnh if/else, mỗi cặp điều kiện và thân được gọi là một nhánh trong câu lệnh when. Tương tự như câu lệnh if/else, bạn có thể thêm một nhánh else làm điều kiện cuối cùng trong câu lệnh when dưới dạng một nhánh chung.

Viết lại câu lệnh if/else bằng câu lệnh when

Trong lập trình đèn giao thông, nhiều nhánh đã có sẵn:

  • Đèn giao thông màu đỏ
  • Đèn giao thông màu vàng
  • Đèn giao thông xanh lục
  • Đèn giao thông màu khác

Chuyển đổi lập trình để sử dụng câu lệnh when:

  1. Trong hàm main(), hãy xóa câu lệnh if/else:
fun main() {
    val trafficLightColor = "Black"

}
  1. Thêm câu lệnh when rồi truyền nó cho biến trafficLightColor dưới dạng đối số:
fun main() {
    val trafficLightColor = "Black"

    when (trafficLightColor) {
    }
}
  1. Trong phần thân của câu lệnh when, hãy thêm điều kiện"Red" theo sau là mũi tên và phần thân println("Stop"):
fun main() {
    val trafficLightColor = "Black"

    when (trafficLightColor) {
        "Red" -> println("Stop")
    }
}
  1. Ở dòng tiếp theo, hãy thêm điều kiện "Yellow" theo sau là mũi tên và phần thân println("Slow"):
fun main() {
    val trafficLightColor = "Black"

    when (trafficLightColor) {
        "Red" -> println("Stop")
        "Yellow" -> println("Slow")
    }
}
  1. Ở dòng tiếp theo, hãy thêm điều kiện "Green" theo sau là mũi tên, kế đến là phần thân println("Go"):
fun main() {
    val trafficLightColor = "Black"

    when (trafficLightColor) {
        "Red" -> println("Stop")
        "Yellow" -> println("Slow")
        "Green" -> println("Go")
    }
}
  1. Ở dòng tiếp theo, hãy thêm từ khóa else theo sau là mũi tên, kế đến là phần thân println("Invalid traffic-light color"):
fun main() {
    val trafficLightColor = "Black"

    when (trafficLightColor) {
        "Red" -> println("Stop")
        "Yellow" -> println("Slow")
        "Green" -> println("Go")
        else -> println("Invalid traffic-light color")
    }
}
  1. Chỉ định lại biến trafficLightColor cho giá trị "Yellow":
fun main() {
    val trafficLightColor = "Yellow"

    when (trafficLightColor) {
        "Red" -> println("Stop")
        "Yellow" -> println("Slow")
        "Green" -> println("Go")
        else -> println("Invalid traffic-light color")
    }
}

Khi chạy chương trình này, bạn nghĩ kết quả sẽ là gì?

  1. Chạy chương trình rồi xem kết quả:
Slow

Sơ đồ chú thích câu lệnh when. Dòng "Đỏ" -> println("Dừng") được chú thích là trường hợp 1. Dòng "Vàng" -> println("Chậm lại") được chú thích là trường hợp 2. Dòng "The Green" -> println("Tiếp tục") được chú thích là trường hợp 3. Dòng else -> println("Màu của đèn giao thông không hợp lệ") được chú thích là trường hợp 4.

Kết quả là thông báo Slow, vì:

  • Biến trafficLightColor được gán giá trị "Yellow".
  • Lập trình này đánh giá từng điều kiện một.
  • Giá trị "Yellow" không bằng giá trị "Red", do đó lập trình sẽ bỏ qua phần thân đầu tiên.
  • Giá trị "Yellow" bằng giá trị "Yellow", do đó lập trình sẽ thực thi phần thân thứ hai và in thông báo Slow.
  • Phần thân đã được thực thi, do đó lập trình sẽ bỏ qua các nhánh thứ ba và thứ tư, đồng thời để lại câu lệnh when.

Viết các điều kiện phức tạp hơn trong câu lệnh when

Hiện tại, bạn đã học được cách viết điều kiện when cho một điều kiện bằng nhau, chẳng hạn như khi biến trafficLightColor được chỉ định giá trị "Yellow". Tiếp theo, bạn sẽ tìm hiểu cách sử dụng dấu phẩy (,), từ khóa inis để tạo các điều kiện when phức tạp hơn.

Tạo lập trình xác định liệu một số từ 1 đến 10 có phải là số nguyên tố hay không:

  1. Mở Kotlin playground trong một cửa sổ riêng.

Bạn sẽ quay lại lập trình đèn giao thông sau.

  1. Xác định biến x rồi chỉ định giá trị 3 cho biến đó:
fun main() {
    val x = 3
}
  1. Thêm câu lệnh when bao gồm nhiều nhánh cho các điều kiện 2,3,57, sau đó theo dõi mỗi nhánh có phần thân println("x is prime number between 1 and 10."):
fun main() {
    val x = 3

    when (x) {
        2 -> println("x is a prime number between 1 and 10.")
        3 -> println("x is a prime number between 1 and 10.")
        5 -> println("x is a prime number between 1 and 10.")
        7 -> println("x is a prime number between 1 and 10.")
    }
}
  1. Thêm một nhánh else có phần thân println("x is not prime number between 1 and 10."):
fun main() {
    val x = 3

    when (x) {
        2 -> println("x is a prime number between 1 and 10.")
        3 -> println("x is a prime number between 1 and 10.")
        5 -> println("x is a prime number between 1 and 10.")
        7 -> println("x is a prime number between 1 and 10.")
        else -> println("x isn't a prime number between 1 and 10.")
    }
}
  1. Chạy lập trình rồi xác minh kết quả như mong đợi:
x is a prime number between 1 and 10.

Sử dụng dấu phẩy (,) cho nhiều điều kiện

Lập trình số nguyên tố chứa nhiều câu lệnh println() lặp lại. Khi viết một câu lệnh when, bạn có thể sử dụng dấu phẩy (,) để biểu thị nhiều điều kiện tương ứng với cùng một phần thân.

Sơ đồ cho thấy cấu trúc của câu lệnh When. Bắt đầu bằng từ khóa when, theo sau là dấu ngoặc đơn có khối parameter (tham số) bên trong. Tiếp theo, bên trong một cặp dấu ngoặc nhọn có hai dòng khối. Ở dòng đầu tiên, có một khối condition 1 (điều kiện 1), theo sau là dấu phẩy, tiếp theo là khối condition 2 (điều kiện 2), theo sau là biểu tượng mũi tên và một khối body (thân). Ở dòng thứ hai, có một khối condition (điều kiện) theo sau là biểu tượng mũi tên và một khối body (thân).

Trong sơ đồ trước, nếu điều kiện đầu tiên hoặc thứ hai được đáp ứng, thì thân tương ứng sẽ được thực thi.

Viết lại lập trình số nguyên tố với khái niệm này:

  1. Ở nhánh với điều kiện 2, hãy thêm 3, 57, phân tách bằng dấu phẩy (,):
fun main() {
    val x = 3

    when (x) {
        2, 3, 5, 7 -> println("x is a prime number between 1 and 10.")
        3 -> println("x is a prime number between 1 and 10.")
        5 -> println("x is a prime number between 1 and 10.")
        7 -> println("x is a prime number between 1 and 10.")
        else -> println("x isn't a prime number between 1 and 10.")
    }
}
  1. Xóa từng nhánh đối với điều kiện 3, 57:
fun main() {
    val x = 3

    when (x) {
        2, 3, 5, 7 -> println("x is a prime number between 1 and 10.")
        else -> println("x isn't a prime number between 1 and 10.")
    }
}
  1. Chạy lập trình rồi xác minh kết quả như mong đợi:
x is a prime number between 1 and 10.

Sử dụngtừ khóa in cho nhiều điều kiện

Bên cạnh biểu tượng dấu phẩy (,) biểu thị nhiều điều kiện, bạn cũng có thể sử dụng từ khóa in và một dải các giá trị trong nhánh when.

Sơ đồ cho thấy cấu trúc của câu lệnh When. Bắt đầu bằng từ khóa when, theo sau là dấu ngoặc đơn có khối parameter (tham số) bên trong. Tiếp theo, bên trong một cặp dấu ngoặc nhọn có hai dòng khối. Ở dòng đầu tiên, có một từ khóa trong, theo sau là một khối range start (điểm bắt đầu phạm vi), hai dấu chấm, một khối range end (điểm kết thúc phạm vi), một biểu tượng mũi tên, sau đó là một khối body (thân). Ở dòng thứ hai, có một khối condition (điều kiện) theo sau là biểu tượng mũi tên và một khối body (thân).

Để sử dụng phạm vi giá trị, hãy thêm một số biểu thị thời điểm bắt đầu của phạm vi, theo sau là 2 dấu chấm mà không có dấu cách, sau đó đóng nó bằng một số khác để cho biết thời điểm kết thúc phạm vi.

Khi giá trị của tham số bằng bất kỳ giá trị nào trong phạm vi giữa phạm vi bắt đầu và kết thúc, phần thân đầu tiên sẽ thực thi.

Trong lập trình số nguyên tố, bạn có thể in thông báo nếu số nằm trong khoảng từ 1 đến 10 nhưng không phải là số nguyên tố không?

Thêm một nhánh khác có từ khóa in:

  1. Sau nhánh đầu tiên của câu lệnh when, hãy thêm nhánh thứ hai có từ khóa in theo sau là phạm vi 1..10 và thân println("x is a number between 1 and 10, but not a prime number."):
fun main() {
    val x = 3

    when (x) {
        2, 3, 5, 7 -> println("x is a prime number between 1 and 10.")
        in 1..10 -> println("x is a number between 1 and 10, but not a prime number.")
        else -> println("x isn't a prime number between 1 and 10.")
    }
}
  1. Thay đổi biến x thành giá trị 4:
fun main() {
    val x = 4

    when (x) {
        2, 3, 5, 7 -> println("x is a prime number between 1 and 10.")
        in 1..10 -> println("x is a number between 1 and 10, but not a prime number.")
        else -> println("x isn't a prime number between 1 and 10.")
    }
}
  1. Chạy chương trình rồi xác minh kết quả:
x is a number between 1 and 10, but not a prime number.

Chương trình in thông báo của nhánh thứ hai nhưng không in được thông báo của nhánh đầu tiên hoặc thứ ba.

Sơ đồ chú thích câu lệnh when. Dòng 2,3,5,7 -> println("x là số nguyên tố từ 1 đến 10.") được chú thích là trường hợp 1. Dòng in 1..10 -> println("x là số từ 1 đến 10, nhưng không phải là số nguyên tố") được chú thích là trường hợp 2. Dòng else -> println("x không phải là số nguyên tố từ 1 và 10.") được chú thích là trường hợp 3.

Dưới đây là cách hoạt động của lập trình này:

  • Biến x được gán giá trị 4.
  • Lập trình này tiến hành đánh giá các điều kiện cho nhánh đầu tiên. Giá trị 4 không phải là các giá trị 2, 3, 5 hoặc 7, vì vậy, chương trình sẽ bỏ qua việc thực thi phần thân của nhánh đầu tiên và chuyển sang giá trị nhánh thứ hai.
  • Giá trị 4 nằm trong khoảng từ 1 đến 10, do đó thông báo phần thân của x is a number between 1 and 10, but not a prime number. sẽ được in.
  • Một phần thân được thực thi, vì vậy, chương trình sẽ tiếp tục rời khỏi câu lệnh when và bỏ qua nhánh else.

Dùng từ khóa is để kiểm tra loại dữ liệu

Bạn có thể dùng từ khóa is làm điều kiện để kiểm tra loại dữ liệu của một giá trị được đánh giá.

Sơ đồ cho thấy cấu trúc của câu lệnh When. Bắt đầu bằng từ khóa when, theo sau là dấu ngoặc đơn có khối parameter (tham số) bên trong. Tiếp theo, bên trong một cặp dấu ngoặc nhọn có hai dòng khối. Ở dòng đầu tiên, có một từ khóa trong, theo sau là một khối type (loại), một biểu tượng mũi tên, sau đó là một khối body (thân). Ở dòng thứ hai, có một khối condition (điều kiện), theo sau là biểu tượng mũi tên rồi đến một khối body (thân).

Trong sơ đồ trước, nếu giá trị của đối số thuộc loại dữ liệu đã nêu, thì phần thân đầu tiên sẽ được thực thi.

Trong lập trình số nguyên tố, bạn có thể in thông báo nếu đầu vào là một số nguyên nằm ngoài phạm vi từ 1 đến 10 không?

Thêm một nhánh khác có từ khóa is:

  1. Sửa đổi x thành loại Any. Điều này cho thấy x có thể có giá trị khác với loại Int.
fun main() {
    val x: Any = 4

    when (x) {
        2, 3, 5, 7 -> println("x is a prime number between 1 and 10.")
        in 1..10 -> println("x is a number between 1 and 10, but not a prime number.")
        else -> println("x isn't a prime number between 1 and 10.")
    }
}
  1. Sau nhánh thứ hai của câu lệnh when, hãy thêm từ khóa is và loại dữ liệu Int có phần thân println("x is an integer number, but not between 1 and 10."):
fun main() {
    val x: Any = 4

    when (x) {
        2, 3, 5, 7 -> println("x is a prime number between 1 and 10.")
        in 1..10 -> println("x is a number between 1 and 10, but not a prime number.")
        is Int -> println("x is an integer number, but not between 1 and 10.")
        else -> println("x isn't a prime number between 1 and 10.")
    }
}
  1. Trong nhánh else, hãy thay đổi thân thành println("x isn't an integer number."):
fun main() {
    val x: Any = 4

    when (x) {
        2, 3, 5, 7 -> println("x is a prime number between 1 and 10.")
        in 1..10 -> println("x is a number between 1 and 10, but not a prime number.")
        is Int -> println("x is an integer number, but not between 1 and 10.")
        else -> println("x isn't an integer number.")
    }
}
  1. Thay đổi biến x thành giá trị 20:
fun main() {
    val x: Any = 20

    when (x) {
        2, 3, 5, 7 -> println("x is a prime number between 1 and 10.")
        in 1..10 -> println("x is a number between 1 and 10, but not a prime number.")
        is Int -> println("x is an integer number, but not between 1 and 10.")
        else -> println("x isn't an integer number.")
    }
}
  1. Chạy chương trình rồi xác minh kết quả:
x is an integer number, but not between 1 and 10.

Lập trình in thông báo của nhánh thứ ba, nhưng không in các thông báo của nhánh thứ nhất, thứ hai hoặc thứ tư.

Sơ đồ chú thích câu lệnh when. Dòng 2,3,5,7 -> println("x là số nguyên tố từ 1 đến 10.") được chú thích là trường hợp 1. Dòng in 1..10 -> println("x là số từ 1 đến 10, nhưng không phải là số nguyên tố") được chú thích là trường hợp 2. Dòng is Int -> println("x là một số nguyên nhưng không nằm trong khoảng từ 1 đến 10.") được chú thích là trường hợp 3. Dòng else -> println("x không phải là số nguyên.") được chú thích là trường hợp 4.

Dưới đây là cách hoạt động của lập trình:

  • Biến x được gán giá trị 20.
  • Lập trình này tiến hành đánh giá các điều kiện cho nhánh đầu tiên. Giá trị 20 không phải là các giá trị 2, 3, 5 hoặc 7, vì vậy, chương trình sẽ bỏ qua việc thực thi phần thân của nhánh đầu tiên và chuyển sang giá trị nhánh thứ hai.
  • Giá trị 20 không nằm trong phạm vi 1 đến 10, do đó chương trình bỏ qua việc thực thi phần thân của nhánh thứ hai và chuyển sang nhánh thứ ba.
  • Giá trị 20 thuộc loại Int, vì vậy phần thân của x is an integer number, but not between 1 and 10 sẽ được in.
  • Một phần thân được thực thi, vì vậy, chương trình sẽ tiếp tục rời khỏi câu lệnh when và bỏ qua nhánh else.

Dùng thử

Bây giờ, hãy thực hành những gì bạn đã học được trong bài lập trình đèn giao thông.

Hãy tưởng tượng đèn giao thông màu hổ phách ở một số quốc gia cảnh báo người lái xe theo cách tương tự như đèn giao thông màu vàng ở các quốc gia khác. Bạn có thể sửa đổi lập trình này để đáp ứng điều kiện bổ sung và duy trì các điều kiện ban đầu không?

Thêm một điều kiện bổ sung với cùng một nội dung

Thêm một điều kiện bổ sung vào lập trình đèn giao thông:

  1. Nếu bạn vẫn đang mở lập trình, hãy quay lại bản Kotlin Playground với lập trình đèn giao thông.
  2. Nếu bạn đã đóng lập trình, hãy mở một bản mới của Kotlin Playground rồi nhập mã này:
fun main() {
    val trafficLightColor = "Yellow"

    when (trafficLightColor) {
        "Red" -> println("Stop")
        "Yellow" -> println("Slow")
        "Green" -> println("Go")
        else -> println("Invalid traffic-light color")
    }
}
  1. Trong nhánh thứ hai của câu lệnh when, hãy thêm dấu phẩy sau điều kiện "Yellow", sau đó thêm điều kiện "Amber":
fun main() {
    val trafficLightColor = "Yellow"

    when (trafficLightColor) {
        "Red" -> println("Stop")
        "Yellow", "Amber" -> println("Slow")
        "Green" -> println("Go")
        else -> println("Invalid traffic-light color")
    }
}
  1. Thay đổi biến trafficLightColor thành giá trị "Amber":
fun main() {
    val trafficLightColor = "Amber"

    when (trafficLightColor) {
        "Red" -> println("Stop")
        "Yellow", "Amber" -> println("Slow")
        "Green" -> println("Go")
        else -> println("Invalid traffic-light color")
    }
}
  1. Chạy chương trình này rồi xác minh kết quả:
Slow

4. Sử dụng câu lệnh if/else và when như một biểu thức

Bạn đã tìm hiểu cách dùng if/elsewhen dưới dạng câu lệnh. Khi sử dụng điều kiện làm câu lệnh, bạn cho phép mỗi nhánh thực hiện các hành động khác nhau trong phần thân dựa trên các điều kiện.

Bạn cũng có thể sử dụng các điều kiện làm biểu thức để trả về các giá trị khác nhau cho mỗi nhánh điều kiện. Khi phần thân của mỗi nhánh xuất hiện giống nhau, bạn có thể sử dụng biểu thức có điều kiện để cải thiện khả năng đọc mã so với câu lệnh có điều kiện.

Sơ đồ mô tả biểu thức if/else với từ khóa val theo sau là khối name (tên), ký hiệu = (dấu bằng), từ khóa if, dấu ngoặc đơn có condition (điều kiện) bên trong, một cặp dấu ngoặc nhọn có khối body 1 (thân 1) bên trong, một từ khóa else và sau đó là một cặp dấu ngoặc nhọn có khối body (thân) bên trong.

Cú pháp cho điều kiện dưới dạng biểu thức tương tự như câu lệnh, nhưng dòng cuối cùng của thân trong mỗi nhánh cần trả về một giá trị hoặc biểu thức, còn các điều kiện được chỉ định cho một biến.

Nếu thân chỉ chứa một giá trị hoặc biểu thức trả về, bạn có thể xoá dấu ngoặc nhọn để mã ngắn gọn hơn.

Sơ đồ mô tả biểu thức if/else với từ khóa val theo sau là khối name (tên), biểu tượng = (dấu bằng), từ khóa if, dấu ngoặc đơn có condition (điều kiện) bên trong, khối expression 1 (biểu thức 1), từ khóa else và khối expression 2 (biểu thức 2).

Trong phần tiếp theo, bạn hãy xem biểu thức if/else thông qua lập trình đèn giao thông.

Chuyển đổi câu lệnh if thành một biểu thức

Có rất nhiều câu lệnh println() lặp lại trong câu lệnh if/else này:

fun main() {
    val trafficLightColor = "Black"

    if (trafficLightColor == "Red") {
        println("Stop")
    } else if (trafficLightColor == "Yellow") {
        println("Slow")
    } else if (trafficLightColor == "Green") {
        println("Go")
    } else {
        println("Invalid traffic-light color")
    }

}

Chuyển đổi câu lệnh if/else này thành biểu thức if/else và xóa lặp lại này:

  1. Trong Kotlin playground, hãy nhập lập trình đèn giao thông trước đó.
  2. Xác định biến message rồi chỉ định biến đó bằng câu lệnh if/else:
fun main() {
    val trafficLightColor = "Black"

    val message = if (trafficLightColor == "Red") {
        println("Stop")
    } else if (trafficLightColor == "Yellow") {
        println("Slow")
    } else if (trafficLightColor == "Green") {
        println("Go")
    } else {
        println("Invalid traffic-light color")
    }

}
  1. Xóa tất cả câu lệnh println() và dấu ngoặc nhọn, nhưng để lại giá trị bên trong:
fun main() {
    val trafficLightColor = "Black"

    val message =
      if (trafficLightColor == "Red") "Stop"
      else if (trafficLightColor == "Yellow") "Slow"
      else if (trafficLightColor == "Green") "Go"
      else "Invalid traffic-light color"
}
  1. Thêm câu lệnh println() vào cuối lập trình rồi truyền biến message đó dưới dạng đối số:
fun main() {
    val trafficLightColor = "Black"

    val message =
      if (trafficLightColor == "Red") "Stop"
      else if (trafficLightColor == "Yellow") "Slow"
      else if (trafficLightColor == "Green") "Go"
      else "Invalid traffic-light color"

    println(message)
}
  1. Chạy chương trình này rồi xem kết quả:
Invalid traffic-light color

Dùng thử

Chuyển đổi lập trình đèn giao thông để sử dụng biểu thức when thay vì một câu lệnh when:

  1. Trong Kotlin Playground, hãy nhập mã sau:
fun main() {
    val trafficLightColor = "Amber"

    when (trafficLightColor) {
        "Red" -> println("Stop")
        "Yellow", "Amber" -> println("Slow")
        "Green" -> println("Go")
        else -> println("Invalid traffic-light color")
    }
}

Bạn có thể chuyển đổi câu lệnh when thành một biểu thức để không lặp lại câu lệnh println() không?

  1. Tạo biến message và chỉ định biến đó cho biểu thức when:
fun main() {
    val trafficLightColor = "Amber"

    val message = when(trafficLightColor) {
        "Red" -> "Stop"
        "Yellow", "Amber" -> "Proceed with caution."
        "Green" -> "Go"
        else -> "Invalid traffic-light color"
    }
}
  1. Thêm câu lệnh println() vào cuối cùng của lập trình, sau đó truyền vào biến message dưới dạng đối số:
fun main() {
    val trafficLightColor = "Amber"

    val message = when(trafficLightColor) {
        "Red" -> "Stop"
        "Yellow", "Amber" -> "Proceed with caution."
        "Green" -> "Go"
        else -> "Invalid traffic-light color"
    }
    println(message)
}

5. Kết luận

Xin chúc mừng! Bạn đã tìm hiểu về các điều kiện và cách viết các điều kiện đó trong Kotlin.

Tóm tắt

  • Trong Kotlin, bạn có thể đạt được việc phân nhánh bằng các điều kiện if/else hoặc when.
  • Phần thân của nhánh if trong điều kiện if/else chỉ được thực thi khi biểu thức boolean bên trong điều kiện nhánh if trả về giá trị true.
  • Các nhánh else if tiếp theo trong điều kiện if/else chỉ được thực thi khi nhánh if hoặc else if trước đó trả về các giá trị false.
  • Nhánh else cuối cùng trong điều kiện if/else chỉ được thực thi khi tất cả nhánh if hoặc else if trước đó trả về giá trị false.
  • Bạn nên sử dụng điều kiện when để thay thế điều kiện if/else khi có nhiều hơn hai nhánh.
  • Bạn có thể viết các điều kiện phức tạp hơn trong điều kiện when bằng dấu phẩy (,), phạm vi in và từ khóa is.
  • Các điều kiện if/elsewhen có thể hoạt động dưới dạng câu lệnh hoặc biểu thức.

Tìm hiểu thêm