Lập trình Kotlin — Lớp dữ liệu (data class)

Liem Vo
Viet Android Developers
4 min readAug 27, 2020

Kotlin cung cấp cho chúng ta một lớp chuyên dụng cho việc lưu trữ dữ liệu với một số hàm được sinh ra sẵn phục vụ việc này.

Video

Trong bài học trước chúng ta đã tìm hiểu về mở rộng trong Kotlin. Bài học hôm nay sẽ giới thiệu về lớp dữ liệu với mục đích chính là nắm giữ dữ liệu. Trong lập trình Kotlin, nó được gọi là lớp dữ liệu và được đánh dấu với từ khoá data:

data class News(val title: String, val description: String)

Trình biên dịch tự động tạo ra những hàm dưới dựa vào các thuộc tính đã khai báo trong hàm khởi tạo đầu tiên.

  • Cặp equals() / hashCode()
  • Hàm toString() // News(title=Good morning, description=This is a test)
  • componentN(), căn cứ vào số lượng và thứ tự của thuộc tính trong hàm khởi tạo đầu tiên.
  • copy() sẽ hiểu rõ ở phần sau.
fun main() {
val news = News("Good morning", "This is a test")
println(news.hashCode())
println(news.equals(45))
println(news.toString())
println(news.component1())
println(news.component2())
println(news.copy())
}

Để đảm bảo sự rõ nghĩa và thống nhất của các hàm được sinh ra ở trên, lớp dữ liệu phải đáp ứng một số yêu cầu sau:

  • Hàm khởi tạo đầu tiên có ít nhất một thông số
  • Các thông số trong hàm khởi tạo đầu tiên cần phải được khai báo với từ khoá val hoặc var
  • Lớp dữ liệu không thể là abstract, open, sealed hoặc inner
  • Trước kotlin 1.1 các lớp dữ liệu có thể chỉ hiện thực các giao diện (interfaces)

Các hàm được sinh ra cũng tuân theo một số chuẩn của thành viên kế thừa như:

  • Nếu một số hàm như equals(), hashCode() hoặc toString() đã được hiện thực trong lớp dữ liệu hoặc là final trong lớp cha thì chúng không được sinh ra và dùng những hàm đã có sẵn
  • Nếu lớp dữ liệu cha có hàm componentN() và chúng là open và trả về kiểu dữ liệu tương ứng, những hàm này cũng sẽ được sinh ra tự động ở lớp con. Nếu những hàm đó được đánh dấu là final ở lớp cha thì có lỗi xảy ra.
  • Kế thừa từ một lớp đã có sẵn hàm copy với thông số giống như hàm copy của lớp dữ liệu đã bắt đầu không hỗ trợ từ Kotlin 1.2 và không thể được từ Kotlin 1.3

Ví dụ ở lớp dữ liệu trên thì mặc đình là sẽ có hàm copy như sau được sinh ra.

fun copy(title: String, description: String) {}

Nếu lớp News kế thừa từ lớp có sẵn hàm này thì sẽ không được:

open class Test {
open var title: String = ""
open var description: String = ""
open fun copy(title: String, description: String) {}
}

data class News(override var title: String, override var description: String) : Test(){
}
  • Trong lớp dữ liệu sẽ không cho hiện thực các hàm của componentN()copy().

Từ Kotlin 1.1 lớp dữ liệu có thể kế thừa các lớp khác.

Trên máy ảo Java, nếu cần hàm khởi tạo với không tham số thì các giá trị mặc định cần được cung cấp cho lớp dữ liệu.

Thuộc tính khai báo bên trong thân của lớp dữ liệu

Thuộc tính bên trong lớp dữ liệu sẽ không được sinh ra cùng với những thành viên tự động sinh ra của lớp dữ liệu

data class Animal(val name: String) {
var legs: Int = 0
}

fun main() {
val cat = Animal("Cat")
cat.legs = 4
println(cat)
}

Hàm copy

Sẽ sao chép lại lớp dữ liệu với một số dữ liệu thay đổi.

fun copy(title: String = this.title, description: String = thisdescription) = News(title, description)

Các lớp dữ liệu và khai báo cấu trúc (destructuring declarations)

Các hàm component được sinh ra cho phép lớp dữ liệu được dùng trong khai báo cấu trúc.

val (title, description) = news
println("$title, $description of news")

Các lớp dữ liệu chuẩn

Thư viện chuẩn cung cấp Pair và Triple. Trong hầu hết các trường hợp, tên của lớp dữ liệu là lựa chọn tốt hơn trong thiết kế, bởi vì chúng làm code dễ đọc hơn và cung cấp tên dễ đọc hơn cho thuộc tính.

Cảm ơn các bạn đã đọc bài. Đăng ký kênh chúng tôi để xem những bài học mới nhất.

Youtube kênh: https://bit.ly/2EFOOXs

Thảo luận bằng cách comment ở đây hoặc trong video của blog này.

--

--