Trang chủHướng dẫnHàm phạm vi trong Kotlin: Let, run, also, apply, with
Java

Hàm phạm vi trong Kotlin: Let, run, also, apply, with

CyStack blog 7 phút để đọc
CyStack blog23/09/2025
Locker Avatar

Chris Pham

Technical Writer

Locker logo social
Reading Time: 7 minutes

Hàm phạm vi trong Kotlin

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

phạm vi trong Kotlin

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 leti sẽ trả về thuộc tính này cho thuộc tính bên ngoài a.

phạm vi trong Kotlin

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àm run cũng trả về câu lệnh cuối cùng.
  • Không giống let, hàm run không hỗ trợ từ khóa it.

Kết hợp letrun (let and run)

Hãy cùng nhau kết hợp các hàm letrun:

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

hàm phạm vi trong Kotlin

Ở 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.

tìm hiểu hàm phạm vi trong Kotlin

So sánh Kotlin letalso

Đoạn code sau đây cho thấy một ví dụ tuyệt vời để phân biệt giữa letalso.

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 applyalso

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 applywith

  • 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 khi apply 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 khi with 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.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất