Trong hướng dẫn này, chúng ta sẽ triển khai một số hàm phạm vi trong Kotlin. Thư viện kotlin-stdlib
cung cấp nhiều hàm bậc cao hữu ích, hiện thực các mẫu lập trình mang tính đặc trưng. Chúng ta sẽ thấy cách mà chúng giúp việc lập trình với Kotlin trở nên dễ dàng và nhanh chóng hơn. Các hàm sẽ được thảo luận bên dưới bao gồm:
let
run
also
apply
with
Các hàm phạm vi trong Kotlin
1. Kotlin let
Hàm let
nhận đối tượng mà nó được gọi lên làm tham số và trả về kết quả của biểu thức lambda. let
trong Kotlin là một scoping function, nghĩa là các biến được khai báo bên trong biểu thức không thể sử dụng bên ngoài phạm vi của nó. Một ví dụ minh họa cách hàm let
hoạt động như sau:
fun main(args: Array<String>) {
var str = "Hello World"
str.let { println("$it!!") }
println(str)
}
//Prints
//Hello World!!
//Hello World
Từ khóa it
chứa một bản sao của thuộc tính bên trong let
. Giá trị cuối cùng từ khối let
sẽ được trả về như một đối số, bạn có thể xem ví dụ dưới đây:
var strLength = str.let { "$it function".length }
println("strLength is $strLength") //prints strLength is 25
Chuỗi các hàm let
Chúng ta có thể nối nhiều hàm let
với nhau để thực hiện một chuỗi các thao tác:
var a = 1
var b= 2
a = a.let { it + 2 }.let { val i = it + b
i}
println(a) //5
Như bạn thấy, chúng ta đã khai báo một biến cục bộ “i” bên trong hàm let
thứ hai. Việc đặt câu lệnh cuối cùng của hàm let
là i
sẽ trả về thuộc tính này cho thuộc tính bên ngoài a
.
Lồng hàm let
Chúng ta có thể lồng một biểu thức let
bên trong một biểu thức let
khác như sau:
var x = "Anupam"
x.let { outer -> outer.let { inner -> print("Inner is $inner and outer is $outer") } }
//Prints
//Inner is Anupam and outer is Anupam
Đối với let
lồng nhau, chúng ta không thể sử dụng từ khóa it
mặc định. Chúng ta cần gán tên rõ ràng cho it
trong cả hai hàm let
. Chỉ let
bên ngoài cùng trả về giá trị, như ví dụ dưới đây:
var x = "Anupam"
x = x.let { outer ->
outer.let { inner ->
println("Inner is $inner and outer is $outer")
"Kotlin Tutorials Inner let"
}
"Kotlin Tutorials Outer let"
}
println(x) //prints Kotlin Tutorials Outer let
let
để kiểm tra null
Ngoài ra, let
rất hữu ích cho việc kiểm tra các thuộc tính Nullable
như ví dụ dưới đây:
var name : String? = "Kotlin let null check"
name?.let { println(it) } //prints Kotlin let null check
name = null
name?.let { println(it) } //nothing happens
Mã bên trong biểu thức let
sẽ chỉ được thực thi khi thuộc tính không null. Như vậy, let
giúp chúng ta loại bỏ những khối kiểm tra null if-else
dài dòng!
2. Kotlin run
Kotlin run
là một hàm khác cũng rất thú vị. Ví dụ sau đây minh họa các trường hợp sử dụng của nó:
var tutorial = "This is Kotlin Tutorial"
println(tutorial) //This is Kotlin Tutorial
tutorial = run {
val tutorial = "This is run function"
tutorial
}
println(tutorial) //This is run function
Biểu thức run
trong Kotlin có thể thay đổi thuộc tính bên ngoài. Do đó, trong đoạn code trên, chúng ta đã định nghĩa lại nó cho phạm vi cục bộ.
- Tương tự như hàm
let
, hàmrun
cũng trả về câu lệnh cuối cùng. - Không giống
let
, hàmrun
không hỗ trợ từ khóait
.
Kết hợp let
và run
(let and run)
Hãy cùng nhau kết hợp các hàm let
và run
:
var p : String? = null
p?.let { println("p is $p") } ?: run { println("p was null. Setting default value to: ")
p = "Kotlin"}
println(p)
//Prints
//p was null. Setting default value to:
//Kotlin
Trong ví dụ này, chúng ta sử dụng ?.let
để kiểm tra p
có null không. Nếu p
không null, nó sẽ in giá trị của p
. Nếu p
là null, toán tử Elvis (?:
) sẽ chuyển quyền điều khiển sang khối run
, nơi chúng ta in ra thông báo và gán giá trị mặc định cho p
.
3. Kotlin also
Đúng như tên gọi, biểu thức also
thực hiện một số xử lý bổ sung trên đối tượng mà nó được gọi. Không như let
, nó trả về chính đối tượng gốc thay vì một dữ liệu trả về mới. Do đó, dữ liệu trả về luôn có cùng kiểu. Giống let
, also
cũng sử dụng it
.
var m = 1
m = m.also { it + 1 }.also { it + 1 }
println(m) //prints 1
Ở ví dụ trên, mặc dù chúng ta đã thực hiện it + 1
hai lần, giá trị của m
vẫn là 1 vì also
luôn trả về đối tượng gốc (ở đây là m
) chứ không phải kết quả của biểu thức lambda.
So sánh Kotlin let
và also
Đoạn code sau đây cho thấy một ví dụ tuyệt vời để phân biệt giữa let
và also
.
data class Person(var name: String, var tutorial : String)
var person = Person("Anupam", "Kotlin")
var l = person.let { it.tutorial = "Android" }
var al = person.also { it.tutorial = "Android" }
println(l)
println(al)
println(person)
Trong đoạn code trên, chúng ta đã sử dụng Data classes. Biểu thức also
trả về đối tượng data class
đã được sửa đổi, trong khi biểu thức let
trả về Unit
vì chúng ta không chỉ định bất cứ điều gì một cách rõ ràng để nó trả về.
4. Kotlin apply
Kotlin apply
là một extension function trên một kiểu dữ liệu. Nó thực thi trên đối tượng tham chiếu (còn gọi là receiver) vào biểu thức và trả về chính đối tượng tham chiếu đó khi hoàn thành.
data class Person(var name: String, var tutorial : String)
var person = Person("Anupam", "Kotlin")
person.apply { this.tutorial = "Swift" }
println(person)
// Prints: Person(name=Anupam, tutorial=Swift)
So sánh apply
và also
data class Person(var n: String, var t : String)
var person = Person("Anupam", "Kotlin")
person.apply { t = "Swift" }
println(person) // Person(n=Anupam, t=Swift)
person.also { it.t = "Kotlin" }
println(person) // Person(n=Anupam, t=Kotlin)
Lưu ý: Trong apply
, từ khóa it
không được phép. Nếu tên thuộc tính của data class
là duy nhất trong hàm, bạn có thể bỏ qua this
. Chúng ta nên sử dụng also
chỉ khi chúng ta không muốn che khuất this
và muốn truy cập đối tượng bằng it
. apply
rất hữu ích để cấu hình đối tượng.
5. Kotlin with
Giống apply
, with
được sử dụng để thay đổi các thuộc tính của instance mà không cần phải gọi toán tử dấu chấm (.
) trên đối tượng tham chiếu mỗi lần.
data class Person(var name: String, var tutorial : String)
var person = Person("Anupam", "Kotlin")
with(person)
{
name = "No Name"
tutorial = "Kotlin tutorials"
}
println(person) // Prints: Person(name=No Name, tutorial=Kotlin tutorials)
Một lần nữa, with
tương tự apply
nhưng có một vài điểm khác biệt chính.
So sánh Kotlin apply
và with
with
chạy mà không cần một đối tượng (receiver) để gọi, nó nhận đối tượng làm đối số. Trong khiapply
là một extension function nên nó cần một đối tượng để gọi.apply
chạy trên đối tượng tham chiếu (this
), trong khiwith
chỉ truyền đối tượng đó như một đối số đầu tiên.- Biểu thức cuối cùng của hàm
with
trả về một kết quả.
var xyz = with(person)
{
name = "No Name"
tutorial = "Kotlin tutorials"
val xyz = "End of tutorial"
xyz
}
println(xyz) //End of tutorial
Trong ví dụ này, xyz
sẽ nhận giá trị “End of tutorial” vì đó là câu lệnh cuối cùng trong khối with
.
Kết luận
Chúng ta vừa hoàn thành một hành trình thú vị qua các hàm tiện ích mạnh mẽ của kotlin-stdlib
. Chúng ta thấy rõ cách let
, run
, also
, apply
, và with
giúp chúng ta viết code Kotlin một cách gọn gàng hơn, dễ đọc hơn và an toàn hơn, đặc biệt là khi làm việc với các đối tượng và xử lý null. Việc làm chủ các hàm này chắc chắn sẽ nâng cao kỹ năng lập trình Kotlin của bạn lên một tầm cao mới.