Kotlin property field
1. Khai báo property
Các class
trong Kotlin có thể có các property
. Chúng có thể khai báo là các biến - sử dụng từ khóa var
hoặc các constant - sử dụng từ khóa val
.
Java
Kotlin
Để sử dụng các property
này, chúng ta chỉ cần access đến chúng bằng tên, hoặc bằng các hàm getter/setter
như trong Java
Java
Kotlin
2. Các hàm getter/setter
Cấu trúc đầy đủ của khai báo property
trong Kotlin là:
Trong đó, giá trị khởi tạo, và các hàm getter/setter
là không bắt buộc, kiểu dữ liệu cũng là không bắt buộc nếu nó có thể được suy ra từ việc khởi tạo (hoặc từ kiểu của mà hàm getter
trả về, sẽ được nói phía sau). Tuy nhiên, để code được trong sáng, lời khuyên là nên thêm kiểu của thuộc tính khi khai báo.
Với các constant, việc khai báo sử dụng từ khóa val
và không được định nghĩa hàm setter
:
Với các hàm getter/setter
, nếu không được định nghĩa, các hàm getter/setter
mặc định sẽ được sử dụng. Chúng ta có thể định nghĩa các hàm này ngay sau việc khai báo các property
. Mặc định, tên của param
của hàm setter
là value
. Tuy nhiên, bạn có thể chọn một cái tên khác. Nếu thích!
Từ Kotlin 1.1, bạn có thể bỏ qua kiểu dữ liệu của property
nếu nó có thể được suy ra từ kiểu trả về của hàm getter
:
Ngoài ra, ta cũng có thể xác định visibility modifier của hàm setter
. Lưu ý: modifier của setter
phải có phạm vi không được lớn hơn phạm vi modifier của property
. Với getter
, chúng ta không thể thay đổi modifier của hàm getter
bởi modifier của getter
phải giống với modifier của property
. Bạn cũng có thể chỉ xác định lại modifier của hàm setter
mà không cần implement hàm đó:
3. Backing field
Trong một VD ở phía trên trên, ta có thể thấy một biến xuất hiện trong các hàm getter/setter
tự định nghĩa, đó là field
. Lưu ý, field
chỉ có thể sử dụng bên trong các hàm getter/setter
và field
sẽ được tự động gen cho property
nếu một trong các hàm getter/setter
tham chiếu đến nó. Nếu không, property
sẽ không có field
. Nhưng vì sao phải dùng field
thay vì dùng property
một cách trực tiếp như thế này:
Như trong một vd ở trên đã đề cập, khi bạn access đến một property
:
Khi này, thực chất, hàm setter
và getter
của property name
sẽ được gọi chứ không phải bạn đang access trực tiếp đến name
. Bởi vậy, trong các hàm getter/setter
tự định nghĩa, nếu sử dụng trực tiếp các property
(vd hàm getter
), Kotlin sẽ gọi lại chính hàm getter
đó, từ đó gây ra tràn bộ nhớ Stack - StackOverflowError
.
4. Backing property
Nếu bạn không quen (hoặc không thích) cách dùng field
ở trên, bạn có thể sử dụng backing property. Việc này tương tự như trong Java, và các hàm getter/ setter
sẽ được tối ưu để việc tràn bộ nhớ không xảy ra. Tuy nhiên, việc viết code sẽ vất vả hơn, tất nhiên rồi:
Trong VD trên, property
mà chúng ta sử dụng để lưu dữ liệu là _table
còn table
chỉ là cách thức để chúng ta truy cập đến _table
.
5. Compile-time constant
Các thuộc tính mà giá trị của chúng được biến đến lúc compile có thể được đánh dấu là compile time constant, sử dụng từ khóa const
. Những property
để đạt được cần thỏa mãn nhưng yêu cầu sau:
Là top-level
property
hoặc là member của mộtobject
(object trong Kotlin là một singleton, không phải là đối tượng)Được khởi tạo với kiểu
String
hoặc kiểu nguyên thủy(Int, Float, Char, Boolean...), không thể là một đối tượng được định nghĩaKhông được có hàm
getter
tự định nghĩa
6. Late-initialized property (Khởi tạo chậm các thuộc tính)
Bình thường, khi các property
được khai báo trong class mà thuộc kiểu non-null phải được khởi tạo: trực tiếp hoặc bằng constructor. Tuy nhiên, việc này không được tiện cho lắm. VD: property
có thể được khởi tạo thông qua Dependency injection hoặc được khởi tạo bên trong method setup của một unit tets hoặc được gán trong một method khác bên trong class. Bởi vậy, Kotlin cung cấp cơ chế cho phép delay việc khởi tạo: từ khóa lateinit
Yêu cầu để sử dụng được từ khóa lateinit
là:
Phải sử dụng với
var property
được khai báo bên trong một class nhưng không phải là trong primary constructor. -property
này không được có các hàmgetter/setter
tự định nghĩa mà phải dùng các hàm mặc địnhKiểu của các
property
này phải là non-null và không thể là kiểu dữ liệu nguyên thủy(Int, Float,Char, Boolean...)Nếu truy cập các
property
này khi chúng chưa được khởi tạo, xin chúc mừng:kotlin.UninitializedPropertyAccessException
sẽ xuất hiện.
7. Overriding property (Ghi đè các property)
Trong Kotlin, chúng ta có thể ghi đè các property
bằng cách sử dụng từ khóa override
tương tự như override các method.
Đặc biệt, chúng ta có thể override lại một val
property bằng một var
property, nhưng không thể làm điều ngược lại. Điều này được phép bởi vì một val
property đã khai báo hàm getter
, và khi override lại nó là var
, chúng ta cần viết thêm hàm setter
trong class con.
Từ khóa override
cũng có thể sử dụng ngay trong primary constructor: