Lớp dữ liệu
Thuộc phần Lập trình hướng đối tượng trong hành trình Kotlin của Coddy. Bài học 32 trên 57.
lớp dữ liệu là lớp có nhiệm vụ chính là lưu trữ dữ liệu. Từ bổ nghĩa data giúp trình biên dịch tạo toString(), equals(), hashCode(), copy() và componentN() từ các thuộc tính của hàm khởi tạo chính:
data class Point(val x: Int, val y: Int)Bên trong main:
val a = Point(1, 2)
val b = Point(1, 2)
println(a)
println(a == b)
println(setOf(a, b).size)Đầu ra:
Point(x=1, y=2)
true
1Khi không có data, println hiển thị tên lớp và một mã băm như Point@1b6d3586, còn hai đối tượng có cùng giá trị thì không bằng nhau. copy() tạo một đối tượng mới với một số thuộc tính đã thay đổi và giữ nguyên đối tượng ban đầu, vì vậy lớp dữ liệu có các thuộc tính val hoạt động như một giá trị bất biến:
data class User(val name: String, val email: String, val admin: Boolean = false)Bên trong main:
val ada = User("Ada", "ada@example.com")
val boss = ada.copy(admin = true)
println(ada)
println(boss)
println(ada == boss)Đầu ra:
User(name=Ada, email=ada@example.com, admin=false)
User(name=Ada, email=ada@example.com, admin=true)
falseKhai báo phân rã tách một đối tượng thành các biến: val (x, y) = point gọi component1() và component2() được tạo tự động theo thứ tự của hàm khởi tạo. Cách này cũng dùng được trong vòng lặp for và tham số lambda. _ bỏ qua một thuộc tính:
data class Score(val player: String, val points: Int, val level: Int)Bên trong main:
val scores = listOf(Score("ada", 120, 3), Score("bo", 95, 2))
for ((player, points) in scores) println("$player: $points")
val (_, bestPoints, bestLevel) = scores.maxBy { it.points }
println("best: $bestPoints at level $bestLevel")Đầu ra:
ada: 120
bo: 95
best: 120 at level 3Chỉ các thuộc tính trong hàm khởi tạo chính mới được tính: thuộc tính khai báo trong thân lớp sẽ không được đưa vào toString, equals, hashCode và copy. Lớp dữ liệu cần ít nhất một tham số hàm khởi tạo, và mọi tham số phải là val hoặc var:
data class Reading(val sensor: String, val value: Int) {
var note = ""
}Bên trong main:
val r1 = Reading("t1", 20)
val r2 = Reading("t1", 20)
r1.note = "checked"
println(r1)
println(r1 == r2)Đầu ra:
Reading(sensor=t1, value=20)
trueThử thách
DễBiến Book thành lớp dữ liệu để khi in ra, lớp hiển thị giá trị và so sánh theo giá trị. Sau đó hoàn thành ba hàm: parse(line) chuyển Dune;Herbert;1965 thành một Book, newEdition(book, year) trả về một bản sao có năm mới và thêm (new edition) vào tiêu đề, còn describe(book) trả về Dune by Herbert, 1965 bằng cách dùng khai báo phân rã.
Code được cung cấp phân tích từng dòng đầu vào, in ra từng cuốn sách, số lượng bản trùng lặp, ấn bản mới của cuốn sách đầu tiên (năm 2024) và phần mô tả của từng cuốn sách riêng biệt.
Đặt code của bạn trong Book.kt và BookTools.kt. Main.kt chứa code đầu vào/đầu ra được cung cấp và bạn không thể chỉnh sửa tệp này.
Tự làm thử
fun main() {
// Đoạn code đầu vào/đầu ra có sẵn: giữ nguyên
val input = generateSequence(::readLine).toList()
val books = input.map { parse(it) }
for (b in books) println(b)
println("duplicates: ${books.size - books.distinct().size}")
println(newEdition(books[0], 2024))
for (b in books.distinct()) println(describe(b))
}
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Lớp và đối tượng
Làm việc với tệpĐịnh nghĩa lớpHàm khởi tạo chínhKhối init và kiểm tra tính hợp lệHàm khởi tạo phụÔn tập: thẻ thư viện4Kế thừa
Lớp mở và lớp conGhi đè thành viênsuper và hàm khởi tạoLớp trừu tượngÔn tập: Danh bạ nhân viên7Các lớp đặc biệt
Lớp dữ liệuLớp enumHệ phân cấp sealedequals, hashCode, toStringÔn tập: Theo dõi đơn hàng2Thuộc tính và tính đóng gói
Trình truy cập tùy chỉnhBộ sửa đổi phạm vi truy cậpSetter riêng tưlazy và lateinitÔn tập: tài khoản ngân hàng5Giao diện
Khai báo giao diệnPhương thức mặc địnhNhiều giao diệnGiao diện như kiểu dữ liệuÔn tập: Phương thức thanh toánTự luyện tập: Playground Kotlin