Lập trình Kotlin — thuộc tính và trường

Liem Vo
Viet Android Developers
4 min readAug 18, 2020

Trong bài học trước chúng ta đã tìm hiểu về lớp và tính kế thừa (lớp, hàm, thuộc tính). Trong bài học hôm nay sẽ học về thuộc tính hoặc trường trong lớp của ngôn ngữ Kotlin.

Khai báo thuộc tính

Các thuộc tính trong lớp của ngôn ngữ Kotlin có thể khai báo theo biến và hằng. Biến được khai báo

class Student {
var name: String = "Student A"
var studentNumber: Int = 3920
var className: String = "Math"
}

Để dùng thuộc tính, chỉ cần dùng tên của thuộc tính. Ví dụ sau in ra tên của học sinh từ lớp vừa rồi.

fun main() {
val student = Student()
println("Student has name: ${student.name}")
}

Getters và setters

Cấu trúc đầy đủ của khai báo thuộc tính như sau:

var <propertyName>[: <PropertyType>] [= <property_initializer
[<getter>]
[<setter>]

Giá trị khởi tạo, getter và setter là không bắt buộc. Kiểu dữ liệu không cần chỉ rõ nếu đã khai báo giá trị khởi tạo.

Ví dụ:

var defaultValue: Int? // lỗi không có giá trị khởi tạo
var initialized = 3 // ngầm hiểu là kiểu int

Ở đây là những thuộc tính có thể thay đổi giá trị. Đối với thuộc tính không thay đổi giá trị thì được khai báo với từ khoá val và chỉ hỗ trợ get.

class Student {
val name: String? // cần phải khởi tạo giá trị trong khối khởi tạo
val isAdult = false

init {
name = "A"
}
}

Giá trị của get có thể tuỳ chỉnh lúc gọi bằng cách dùng từ khoá get hay còn được gọi là thuộc tính được tính. Giá trị của nó thay đổi mỗi lần gọi thuộc tính đó.

val currentTime: Long
get() = System.currentTimeMillis()

Thiết lập tuỳ chỉnh (custom setter), nó sẽ được gọi mỗi lần chúng ta gán giá trị cho thuộc tính. Và nó có định dạng như sau.

var name: String?
set(value) {
println(value)
println(name)
}
get() = "test"

Từ Kotlin 1.1 chúng ta có thể lượt bỏ kiểu trong getter.

val currentTime // ngầm hiểu là kiểu Long
get() = System.currentTimeMillis()

Chúng ta có thể giới hạn phạm vi của getter hoặc setter với một số từ khóa như private, internal bằng cách thêm vào trước get

var name: String?
internal set

Tương tự Kotlin cũng hỗ trợ annotation cho get

var name: String?
@Inject set

Trường sao lưu — Backing Fields

Trường không thể được khai báo trong các lớp của ngôn ngữ Kotlin. Tuy nhiên, khi một thuộc tính cần một trường sao lưu thì, Kotlin tự cung cấp một cách tự động. Trường sao lưu này chỉ đến người truy cập đến một trường xác định:

var age = 0
set(value) {
if (value > 0) field = value
}

Một trường xác định chỉ được dùng trong việc truy cập thuộc tính.

Thuộc tính sao lưu — Backing property

Nếu một số kiểu dữ liệu không được hỗ trợ trông trường sao lưu thì chúng ta sẽ dùng một số đối tượng khác được gọi là thuộc tính sao lưu

class Subject(name: String, credit: Int) {}
class Student {
private var _subject: Subject? = null
val subject: Subject
get() {
if (_subject == null) _subject = Subject("Math", 12)
return _subject ?: throw AssertionError("Set to null by another thread")
}
}

Hằng số lúc biên dịch — Compile-Time constant

Nếu giá trị của thuộc tính chỉ đọc được biết đến tại thời điểm biên dịch thì cần được khai báo với const

Những điều lưu ý với dùng const.

  • Mức cao nhất của file, thành viên trong object hoặc companion object
  • Kiểu dự liệu String, hoặc một kiểu cơ bản
  • Không thể thay đổi giá trị trả về
const val CURRENT_YEAR = 2020

Biến hoặc thuộc tính khởi tạo sau

Trong Kotlin, thông thường thuộc tính khai báo not null thì cần có giá trị khởi tạo nhưng chúng ta có thể không cần khởi tạo giá trị bằng cách thêm từ khoá lateinit vào trước. Thuộc tính này thường được dùng cho dependency injection hoặc trong unit test. Giá trị gán không thể là giá trị null do đó chúng ta phải kiểm tra trước khi gán giá trị.

lateinit var name: String

Ở đây chúng ta có thể giới hạn phạm vi gán giá trị của nó nhưng thuộc tính thay đổi thông thường.

Việc truy cập giá trị của biến khởi tạo sau sẽ xảy ra lỗi nếu nó chưa được gán giá trị. Do đó chúng ta cần phải kiểm tra trước khi truy cập. Với isInitialized

fun printName() {
if (::name.isInitialized) {
println(name)
}
}

Video bài giảng

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.

Tham khảo https://kotlinlang.org/docs/reference/properties.html

--

--