Chào mừng các bạn đến với Cafedev, nơi mà chúng tôi không chỉ chia sẻ kiến thức mà còn là nơi thắp lên đam mê về lập trình. Hôm nay, chúng tôi sẽ cùng nhau khám phá về Kotlin với khai báo tạo nhiều biến (Destructuring Declarations). Đây không chỉ là một khái niệm mạnh mẽ trong ngôn ngữ lập trình Kotlin mà còn là một công cụ linh hoạt giúp chúng ta tận dụng triệt để sức mạnh của ngôn ngữ này. Hãy cùng nhau khám phá những khái niệm thú vị trong Kotlin và cách chúng ta có thể ứng dụng chúng trong công việc hàng ngày.”

Đôi khi, việc destructuring một đối tượng thành nhiều biến là rất tiện lợi, ví dụ như:

val (name, age) = person

Cú pháp này được gọi là destructuring declaration. Một destructuring declaration tạo ra nhiều biến cùng một lúc. Bạn đã khai báo hai biến mới: nameage, và có thể sử dụng chúng độc lập:

println(name)
println(age)

Một destructuring declaration được biên dịch xuống mã sau:

val name = person.component1()
val age = person.component2()

Các hàm component1()component2() là một ví dụ khác về nguyên tắc của quy ước được sử dụng rộng rãi trong Kotlin (xem các toán tử như +*, for-loops là một ví dụ). Bất cứ thứ gì có thể ở bên phải của một destructuring declaration, miễn là số lượng hàm component đủ có thể được gọi trên nó. Và, tất nhiên, có thể có component3()component4() và cứ thế.

Các hàm componentN() cần được đánh dấu bằng từ khóa operator để cho phép sử dụng chúng trong một destructuring declaration.
Destructuring declarations cũng hoạt động trong for-loops:

for ((a, b) in collection) { … }

Biến ab nhận giá trị được trả về bởi component1()component2() gọi trên các phần tử của bộ sưu tập.

1. Ví dụ: trả về hai giá trị từ một hàm

Giả sử bạn cần trả về hai điều từ một hàm – ví dụ, một đối tượng kết quả và một trạng thái nào đó. Một cách gọn gàng để làm điều này trong Kotlin là khai báo một data class và trả về một thể hiện của nó:

data class Result(val result: Int, val status: Status)
fun function(...): Result {
    // computations

    return Result(result, status)
}

// Now, to use this function:
val (result, status) = function(...)

Vì data class tự động khai báo các hàm componentN(), destructuring declarations hoạt động ở đây.

Bạn cũng có thể sử dụng lớp tiêu chuẩn Pair và có function() trả về Pair<int, status>, nhưng thường là tốt hơn khi có tên dữ liệu của bạn đúng cách.

2. Ví dụ: destructuring declarations và maps

Có lẽ cách tốt nhất để duyệt qua một bản đồ là như sau:

for ((key, value) in map) {
   // do something with the key and the value
}

Để làm cho điều này hoạt động, bạn nên
* Trình bày bản đồ như một chuỗi giá trị bằng cách cung cấp một hàm iterator().
* Trình bày từng phần tử dưới dạng cặp bằng cách cung cấp các hàm component1()component2().
Và thực sự, thư viện chuẩn cung cấp các sự mở rộng như vậy:

operator fun <K, V> Map<K, V>.iterator(): Iterator<Map.Entry<K, V>> = entrySet().iterator()
operator fun <K, V> Map.Entry<K, V>.component1() = getKey()
operator fun <K, V> Map.Entry<K, V>.component2() = getValue()

Vì vậy, bạn có thể thoải mái sử dụng destructuring declarations trong for-loops với bản đồ (cũng như các bộ sưu tập của các thể hiện data class hoặc tương tự).

3. Dấu gạch dưới cho biến không sử dụng

Nếu bạn không cần một biến trong destructuring declaration, bạn có thể đặt một dấu gạch dưới thay vì tên của nó:

val (_, status) = getResult()

Các hàm toán tử componentN() không được gọi cho các thành phần được bỏ qua theo cách này.

4. Destructuring trong lambda

Bạn có thể sử dụng cú pháp destructuring declarations cho các tham số lambda. Nếu một lambda có một tham số của kiểu Pair (hoặc Map.Entry, hoặc bất kỳ kiểu nào khác có các hàm componentN phù hợp), bạn có thể tạo nhiều tham số mới thay vì một bằng cách đặt chúng trong dấu ngoặc đơn:

map.mapValues { entry -> "${entry.value}!" }
map.mapValues { (key, value) -> "$value!" }

Lưu ý sự khác biệt giữa việc khai báo hai tham số và việc khai báo một cặp destructuring thay vì một tham số:

{ a -> ... } // one parameter
{ a, b -> ... } // two parameters
{ (a, b) -> ... } // a destructured pair
{ (a, b), c -> ... } // a destructured pair and another parameter

Nếu một thành phần của tham số được destructured không được sử dụng, bạn có thể thay thế nó bằng dấu gạch dưới để tránh phải đặt tên cho nó:

map.mapValues { (_, value) -> "$value!" }

Bạn có thể chỉ định kiểu cho toàn bộ tham số destructured hoặc cho một thành phần cụ thể một cách riêng lẻ:

map.mapValues { (_, value): Map.Entry<int, string=""> -> "$value!" }

map.mapValues { (_, value: String) -> "$value!" }

Chân thành cảm ơn bạn đã dành thời gian đọc về Kotlin với Destructuring Declarations trên Cafedev. Chúng tôi hy vọng rằng thông tin và kiến thức chúng tôi chia sẻ đã giúp bạn mở rộng tầm hiểu biết và kỹ năng lập trình của mình. Nếu có bất kỳ thắc mắc hoặc ý kiến nào, hãy chia sẻ ngay trên Cafedev để chúng tôi có thể học hỏi và cùng nhau xây dựng cộng đồng lập trình viên đầy sức sáng tạo. Đừng quên theo dõi Cafedev để cập nhật những thông tin mới nhất và những bài viết hấp dẫn về công nghệ. Hẹn gặp lại trên Cafedev!

Các nguồn kiến thức MIỄN PHÍ VÔ GIÁ từ cafedev tại đây

Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của Cafedev để nhận được nhiều hơn nữa:

Chào thân ái và quyết thắng!

Đăng ký kênh youtube để ủng hộ Cafedev nha các bạn, Thanks you!