ฟังก์ชันขอบเขต — คืออะไร, ชนิดและการประยุกต์ใช้ใน Kotlin

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-06-23 เวลาอ่าน: 8 นาที

ฟังก์ชันขอบเขตใน Kotlin คือฟังก์ชันไลบรารีมาตรฐานห้าตัว (let, run, with, apply, also) ที่ดําเนินการบล็อกโค้ดในบริบทของอ็อบเจกต์ ฟังก์ชันเหล่านี้แตกต่างกันที่วิธีการเข้าถึงอ็อบเจกต์ (ผ่าน it หรือ this) และค่าที่ส่งคืน (อ็อบเจกต์บริบทหรือผลลัพธ์ของแลมบ์ดา) ตามเอกสาร Kotlin (2026) การเลือกฟังก์ชันขอบเขตที่ถูกต้องจะช่วยลดโค้ดเทมเพลตได้ 25–40% ฟังก์ชันขอบเขต ช่วยเขียนการเริ่มต้น การกําหนดค่า และการแปลงอ็อบเจกต์ในรูปแบบdeclarative

ประเด็นสําคัญ

  • ฟังก์ชันขอบเขต — ฟังก์ชัน Kotlin ห้าตัว (let, run, with, apply, also) สําหรับทํางานในบริบทของอ็อบเจกต์
  • บริบทผ่าน this — run, with, apply ใช้ this ทําให้เรียกเมธอดของอ็อบเจกต์ได้โดยตรง
  • บริบทผ่าน it — let และ also ส่งอ็อบเจกต์เป็นพารามิเตอร์ it พร้อมการตั้งชื่อที่ชัดเจน
  • การส่งคืนอ็อบเจกต์ — apply และ also ส่งคืนอ็อบเจกต์บริบทสําหรับการ chain การเรียก
  • การส่งคืนผลลัพธ์ — let, run และ with ส่งคืนนิพจน์สุดท้ายของแลมบ์ดา

ฟังก์ชันขอบเขตคืออะไร?

ฟังก์ชันขอบเขต คือชุดของฟังก์ชันห้าตัว (let, run, with, apply, also) ที่สร้างไว้ในไลบรารีมาตรฐานของ Kotlin แต่ละฟังก์ชันรับแลมบ์ดาและเปลี่ยนขอบเขตชั่วคราวเพื่อให้โค้ดภายในแลมบ์ดาทํางานในบริบทของอ็อบเจกต์เฉพาะ ซึ่งช่วยลดการซ้ําชื่ออ็อบเจกต์สําหรับการเรียกหลายครั้งและจัดกลุ่มการดําเนินการที่เกี่ยวข้องไว้ในบล็อกเดียว

ลักษณะสําคัญสองประการที่แยกแยะฟังก์ชันขอบเขตคือ วิธีการเข้าถึงอ็อบเจกต์บริบท (ผ่าน this หรือผ่าน it) และค่าที่ส่งคืน (อ็อบเจกต์บริบทเองหรือผลลัพธ์แลมบ์ดา) การเข้าถึงผ่าน this ทําให้อ็อบเจกต์เป็นตัวรับโดยนัย — เมธอดและคุณสมบัติถูกเรียกโดยไม่มีคํานําหน้า การเข้าถึงผ่าน it ส่งอ็อบเจกต์เป็นพารามิเตอร์ที่ชัดเจนของแลมบ์ดา การส่งคืนอ็อบเจกต์ช่วยให้ chain ได้ การส่งคืนผลลัพธ์ช่วยให้กําหนดค่าที่แปลงแล้ว

ในอดีต ฟังก์ชันขอบเขตเกิดขึ้นเพื่อแทนที่รูปแบบ Builder แบบคลาสสิกและตัวแปรชั่วคราวสําหรับการเริ่มต้น แทนที่จะสร้างคลาส builder แยกต่างหาก นักพัฒนาเขียน apply { คุณสมบัติ1 = ...; คุณสมบัติ2 = ... } ซึ่งช่วยลดจํานวนโค้ดและทําให้การเริ่มต้นอ่านง่ายขึ้น ในระบบนิเวศของ Kotlin ฟังก์ชันขอบเขตถูกใช้ในเฟรมเวิร์กและไลบรารีทั้งหมดเป็นสํานวนภาษามาตรฐาน

การเปรียบเทียบฟังก์ชันขอบเขต: this vs it, การส่งคืนอ็อบเจกต์ vs ผลลัพธ์

การเลือกฟังก์ชันขอบเขตที่ถูกต้องถูกกําหนดโดยคําถามสองข้อ: คุณต้องการใช้ this หรือ it เพื่อเข้าถึงอ็อบเจกต์ และคุณต้องการส่งคืนอ็อบเจกต์เองหรือผลลัพธ์แลมบ์ดา การรวมกันของลักษณะไบนารีสองอย่างให้สี่ตัวเลือกที่เป็นไปได้ และ with ครอบครองตําแหน่งพิเศษในฐานะฟังก์ชันเดียวที่ไม่ใช่ส่วนขยาย

ฟังก์ชันการเข้าถึงการส่งคืนส่วนขยาย?สถานการณ์ทั่วไป
letitผลลัพธ์แลมบ์ดาใช่การแปลง, การตรวจสอบ null
runthisผลลัพธ์แลมบ์ดาใช่การคํานวณกับบริบท
withthisผลลัพธ์แลมบ์ดาไม่การจัดกลุ่มการเรียก
applythisอ็อบเจกต์บริบทใช่การเริ่มต้นคุณสมบัติ
alsoitอ็อบเจกต์บริบทใช่ผลข้างเคียง, การบันทึก

เพื่อกําหนดค่าอ็อบเจกต์โดยไม่ส่งคืน ค่าใหม่ ให้ใช้ apply (การเข้าถึงผ่าน this) หรือ also (การเข้าถึงผ่าน it) เพื่อคํานวณค่าใหม่ตามอ็อบเจกต์ ให้ใช้ let (การเข้าถึงผ่าน it) หรือ run (การเข้าถึงผ่าน this) เพื่อจัดกลุ่มการเรียกโดยไม่ต้อง chain ให้ใช้ with การปฏิบัติตามแผนนี้ทําให้โค้ดคาดเดาได้สําหรับนักพัฒนาคนอื่นที่คุ้นเคยกับ Kotlin

apply และ also: การกําหนดค่าด้วยการส่งคืนอ็อบเจกต์

apply คือฟังก์ชันขอบเขตที่ส่งคืนอ็อบเจกต์บริบทและให้การเข้าถึงผ่าน this เป็นเครื่องมือที่เหมาะสําหรับการเริ่มต้นคุณสมบัติของอ็อบเจกต์หลังการสร้าง ภายในบล็อก apply สามารถตั้งค่าคุณสมบัติได้โดยไม่ต้องซ้ําชื่ออ็อบเจกต์ เมธอดส่งคืนอ็อบเจกต์เอง ทําให้สามารถฝัง apply ใน chains หรือใช้ใน initializers

kotlin
data class ServerConfig(
    var host: String = "localhost",
    var port: Int = 8080,
    var useTls: Boolean = false
)

val config = ServerConfig().apply {
    host = "api.example.com"
    port = 443
    useTls = true
}

ในตัวอย่าง apply กําหนดค่า ServerConfig โดยเข้าถึงคุณสมบัติโดยตรงผ่าน this (this ถูกละไว้) หากไม่มี apply จะต้องเขียน config.host = ..., config.port = ... — การอ้างอิงซ้ําสามครั้งไปยังตัวแปรเดียวกัน การส่งคืนอ็อบเจกต์ช่วยให้บันทึกผลลัพธ์การกําหนดค่าใน val config also แตกต่างจาก apply ส่งอ็อบเจกต์ผ่าน it และเหมาะสําหรับผลข้างเคียง

kotlin
fun saveUser(user: User) {
    validate(user).also { result ->
        println("ผลการตรวจสอบ: $result")
    }
    val savedUser = user.also {
        log("Saving user ${it.id}")
        database.save(it)
    }
}

ในตัวอย่าง also ใช้สําหรับการบันทึก — ขณะส่งคืนอ็อบเจกต์ดั้งเดิม จะดําเนินการผลข้างเคียง (แสดงข้อความ) โดยไม่แก้ไขอ็อบเจกต์ นี่คือ chain: validate(user) ส่งคืน User, also บันทึกผลลัพธ์และส่งต่อผู้ใช้ also ยังมีประโยชน์สําหรับการเพิ่มองค์ประกอบในคอลเลกชันหรือการดีบักระหว่าง chain การแปลง

let และ run: การแปลงและการคํานวณ

let คือฟังก์ชันขอบเขตที่ส่งคืนผลลัพธ์แลมบ์ดาและส่งบริบทผ่าน it เป็นฟังก์ชันหลักสําหรับการแปลงที่ปลอดภัยกับ null: ถ้าอ็อบเจกต์เป็น nullable การรวมกัน ?.let { } จะดําเนินการบล็อกสําหรับค่าที่ไม่ใช่ null เท่านั้น let ยังใช้เพื่อจํากัดขอบเขตของตัวแปรชั่วคราวและการแปลงแบบ map จากชนิดหนึ่งไปยังอีกชนิดหนึ่ง

kotlin
fun findUser(id: Int): User?

val displayName = findUser(42)?.let { user ->
    "${user.name} (${user.email})"
} ?: "Unknown user"

// let พร้อมการแปลงคอลเลกชัน
val numbers = listOf("1", "2", "3")
val parsed = numbers.firstOrNull()?.let {
    it.toIntOrNull()
} ?: 0

ในตัวอย่างแรก let ถูกเรียกผ่าน ?. — บล็อกจะดําเนินการก็ต่อเมื่อ findUser ส่งคืนค่าที่ไม่ใช่ null แลมบ์ดารับ user ผ่าน it (สามารถเปลี่ยนชื่อเพื่อความชัดเจน) และส่งคืนสตริงที่จัดรูปแบบแล้ว หากไม่พบผู้ใช้ โอเปอเรเตอร์ Elvis ?: จะให้ค่าเริ่มต้น ในตัวอย่างที่สอง let แปลงสตริงเป็นตัวเลขโดยมีโอกาสเป็น null

run คืออะนาล็อกของ let ที่มีการเข้าถึงผ่าน this ส่งคืนผลลัพธ์แลมบ์ดา run สะดวกสําหรับการคํานวณที่ต้องการบริบทอ็อบเจกต์แต่ส่งคืนค่าใหม่ การเรียก run() โดยไม่มีอ็อบเจกต์ (เช่น run { ... }) สร้างขอบเขตชั่วคราวสําหรับตัวแปร with คือไม่ใช่ส่วนขยายที่มีการเข้าถึงผ่าน this เหมาะสําหรับการจัดกลุ่มการเรียกโดยไม่ต้อง chain

kotlin
// run เป็นการคํานวณตามบริบท
val transformed = listOf(1, 2, 3).run {
    filter { it > 1 }.map { it * 10 }
}
println(transformed) // [20, 30]

// with สําหรับจัดกลุ่มการเรียก
val info = with(StringBuilder()) {
    append("Name: ")
    append("Alice")
    toString()
}

ในตัวอย่าง run บนลิสต์ส่งคืนผลลัพธ์ของการกรองและการแมป — การแปลงเอง ไม่ใช่ลิสต์ with รับ StringBuilder เป็นอาร์กิวเมนต์ (ไม่ผ่านจุด) และทํางานภายในกับ this: append, append, toString ผลลัพธ์ของ with คือสตริง info การเลือกระหว่าง run และ with มักเป็นอัตนัย แต่ with เป็นที่นิยมเมื่ออ็อบเจกต์ถูกส่งมาจากที่อื่นโดยไม่ต้อง chain

with: บริบทที่ไม่ใช่ส่วนขยาย

with แตกต่างจากฟังก์ชันขอบเขตอื่นตรงที่ไม่ใช่ฟังก์ชันส่วนขยาย มันรับอ็อบเจกต์เป็นอาร์กิวเมนต์แรกและแลมบ์ดาเป็นอาร์กิวเมนต์ที่สอง ภายในแลมบ์ดา อ็อบเจกต์สามารถเข้าถึงได้ผ่าน this with สะดวกสําหรับการจัดกลุ่มการเรียกเมธอดอ็อบเจกต์โดยไม่บันทึกผลลัพธ์หรือเมื่อคุณต้องการ "เข้า" สู่บริบทชั่วคราวเพื่ออ่านหลายคุณสมบัติ

kotlin
val user = User("Alice", "alice@example.com", "Admin")

val summary = with(user) {
    "User $name has role $role and email $email"
}
println(summary)

// with สําหรับการเริ่มต้นคอมโพเนนต์ UI
with(TextView(context)) {
    text = "Hello"
    textSize = 18.0f
    setTextColor(Color.BLUE)
}

ในตัวอย่างแรก with สร้างสตริง summary โดยเข้าถึงคุณสมบัติ user โดยตรงผ่าน this หากไม่มี with จะต้องเขียน "User ${user.name} has role ${user.role}" — การซ้ําคําว่า user ในตัวอย่างที่สอง with จัดกลุ่มการกําหนดค่า TextView: เมธอดและคุณสมบัติทั้งหมดถูกเรียกบนอ็อบเจกต์เดียวโดยไม่ซ้ํา ข้อเสียของ with — ไม่สามารถใช้ใน chain ได้เนื่องจากไม่ใช่ส่วนขยายและไม่ส่งคืนอ็อบเจกต์บริบท

คําถามที่พบบ่อย

ควรเลือกฟังก์ชันขอบเขตใดสําหรับการเริ่มต้นอ็อบเจกต์?

ใช้ apply — มันส่งคืนอ็อบเจกต์และให้การเข้าถึงผ่าน this ทําให้สามารถตั้งค่าคุณสมบัติโดยไม่ต้องซ้ําชื่ออ็อบเจกต์ also เหมาะสมหากคุณต้องการพารามิเตอร์ it ที่ชัดเจนเพื่อแยกความแตกต่างจากคุณสมบัติของอ็อบเจกต์

let แตกต่างจาก run อย่างไร?

let ส่งบริบทผ่าน it (พารามิเตอร์ที่ชัดเจน), run — ผ่าน this (ตัวรับโดยนัย) let สะดวกสําหรับการตรวจสอบ null และการแปลง run — สําหรับการคํานวณกับบริบท ทั้งสองส่งคืนผลลัพธ์แลมบ์ดา

เมื่อใดควรใช้ with แทน apply?

with ไม่ใช่ส่วนขยาย — มันรับอ็อบเจกต์เป็นอาร์กิวเมนต์ ใช้ with เพื่อจัดกลุ่มการเรียกเมื่อไม่ต้องการ chain apply เป็นส่วนขยายที่ส่งคืนอ็อบเจกต์ สะดวกใน initializers และรูปแบบ builder

สามารถซ้อนฟังก์ชันขอบเขตหนึ่งภายในอีกอันได้หรือไม่?

ได้ แต่ระวัง this — this ที่ซ้อนกันทําให้เกิดความสับสน ใช้ let หรือ also ที่มีชื่อชัดเจนสําหรับบริบทที่ซ้อนกันเพื่อหลีกเลี่ยงความกํากวมเมื่ออ้างถึงอ็อบเจกต์ภายนอก

ฟังก์ชันขอบเขตใดมีประสิทธิภาพมากที่สุด?

ฟังก์ชันขอบเขตทั้งหมดเป็น inline ดังนั้นจึงไม่สร้างโอเวอร์เฮดจากคลาสที่ไม่ระบุชื่อ ความแตกต่างด้านประสิทธิภาพระหว่างฟังก์ชันเหล่านั้นเล็กน้อย การเลือกควรขึ้นอยู่กับความสามารถในการอ่านและธรรมเนียมปฏิบัติ ไม่ใช่ความเร็ว

สรุป

  • ฟังก์ชันขอบเขต — ฟังก์ชัน inline ของ Kotlin ห้าตัว (let, run, with, apply, also) สําหรับดําเนินการโค้ดในบริบทของอ็อบเจกต์
  • apply ส่งคืนอ็อบเจกต์บริบทพร้อมการเข้าถึงผ่าน this — เหมาะสําหรับการเริ่มต้นคุณสมบัติ
  • also ส่งคืนอ็อบเจกต์บริบทพร้อมการเข้าถึงผ่าน it — เหมาะสําหรับการบันทึกและผลข้างเคียง
  • let ส่งคืนผลลัพธ์แลมบ์ดาพร้อมการเข้าถึงผ่าน it — พื้นฐานสําหรับการแปลงที่ปลอดภัยกับ null
  • run ส่งคืนผลลัพธ์แลมบ์ดาพร้อมการเข้าถึงผ่าน this — สะดวกสําหรับการคํานวณกับบริบท
  • with ไม่ใช่ส่วนขยายและส่งคืนผลลัพธ์แลมบ์ดา — เหมาะสําหรับการจัดกลุ่มการเรียกโดยไม่ต้อง chain
  • การรวมกันของลักษณะ (this/it และการส่งคืนอ็อบเจกต์/ผลลัพธ์) กําหนดการเลือกฟังก์ชันขอบเขตสําหรับแต่ละงาน

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม