การลบชนิดและพารามิเตอร์ชนิด reified
ใช้ reified ร่วมกับฟังก์ชัน inline เพื่อเข้าถึงข้อมูลชนิดขณะรันไทม์
การลบชนิดและพารามิเตอร์ชนิด reified เป็นบทเรียน Kotlin Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Kotlin Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน
การลบชนิดข้อมูลคืออะไร
ขณะรันไทม์ JVM จะลบอาร์กิวเมนต์ชนิดข้อมูลเจเนอริกออก List<String> และ List<Int> จึงเป็นเพียง List ทั้งคู่ ซึ่งจำกัดการดำเนินการด้านชนิดข้อมูลขณะรันไทม์สำหรับเจเนอริก
fun main() {
val strings: List<String> = listOf("a", "b")
val ints: List<Int> = listOf(1, 2)
println(strings.javaClass == ints.javaClass) // true: both ArrayList
println(strings is List<*>) // OK with star
// println(strings is List<String>) // warning: unchecked cast
}ปัญหา: ไม่สามารถตรวจสอบชนิดข้อมูลที่ถูกลบได้
คุณไม่สามารถใช้ is กับอาร์กิวเมนต์ชนิดข้อมูลเจเนอริกที่ระบุเฉพาะได้ เพราะข้อมูลชนิดข้อมูลหายไปแล้วขณะรันไทม์
fun checkType(obj: Any) {
// This works:
if (obj is List<*>) println("It's a list of something")
// This doesn't compile cleanly:
// if (obj is List<String>) println("It's a list of strings") // unchecked
}
fun main() {
checkType(listOf("hello"))
checkType(42)
}สรุปฟังก์ชัน inline
inline จะคัดลอกตัวฟังก์ชันไปยังจุดเรียกใช้ขณะคอมไพล์ สิ่งนี้ทำให้ใช้ reified ได้ โดยอาร์กิวเมนต์ชนิดข้อมูลจะถูกแทนที่ที่จุดเรียกใช้ด้วย
inline fun <T> myRun(block: () -> T): T = block()
fun main() {
val result = myRun { 42 }
println(result) // 42
// The compiler inlines the lambda body — no object allocation
}reified: การเข้าถึง T ขณะรันไทม์
การใช้ inline ร่วมกับ reified จะรักษาอาร์กิวเมนต์ชนิดข้อมูลไว้ที่จุดเรียกใช้ ทำให้ใช้ is, as และ ::class กับ T ได้
inline fun <reified T> isInstance(value: Any): Boolean = value is T
fun main() {
println(isInstance<String>("hello")) // true
println(isInstance<Int>("hello")) // false
println(isInstance<List<*>>(listOf())) // true
}การหาค่า KClass ของ T
เมื่อใช้ reified T คุณสามารถหาค่า T::class ขณะรันไทม์ได้ ซึ่งโดยปกติจะทำไม่ได้ในฟังก์ชันเจเนอริก
inline fun <reified T> classNameOf(): String = T::class.simpleName ?: "Unknown"
fun main() {
println(classNameOf<String>()) // String
println(classNameOf<Int>()) // Int
println(classNameOf<List<*>>()) // List
}การแปลงชนิดอย่างปลอดภัยด้วย reified
ใช้ reified เพื่อเขียนฟังก์ชันช่วยสำหรับแปลงชนิดข้อมูลอย่างปลอดภัย ซึ่งจะคืนค่า null แทนการส่งข้อผิดพลาด
inline fun <reified T> Any?.safeCast(): T? = this as? T
fun main() {
val obj: Any = "Hello"
val s: String? = obj.safeCast<String>()
val i: Int? = obj.safeCast<Int>()
println(s) // Hello
println(i) // null
}การแยกวิเคราะห์ JSON ด้วย reified
ไลบรารีอย่าง Gson หรือ kotlinx.serialization ใช้ reified เพื่ออนุมานชนิดข้อมูลเป้าหมายที่จุดเรียกใช้ โดยไม่ต้องส่งออบเจ็กต์ Class อย่างชัดเจน
import com.google.gson.Gson
// Simulated without real Gson:
inline fun <reified T> parseJson(json: String): T {
return Gson().fromJson(json, T::class.java)
}
// Usage:
// val user: User = parseJson<User>("""{"name":"Alice"}""")reified กับ filterIsInstance
filterIsInstance<T>() ของไลบรารีมาตรฐานใช้ reified เพื่อกรองรายการให้เหลือชนิดข้อมูลเฉพาะ โดยไม่ต้องแปลงชนิดด้วยตนเอง
fun main() {
val mixed: List<Any> = listOf(1, "hello", 2.5, "world", true)
val strings = mixed.filterIsInstance<String>()
val ints = mixed.filterIsInstance<Int>()
println(strings) // [hello, world]
println(ints) // [1]
}ไม่สามารถใช้ reified ในฟังก์ชันที่ไม่ใช่ inline
reified ใช้ได้เฉพาะกับฟังก์ชัน inline เท่านั้น การพยายามใช้โดยไม่มี inline จะทำให้เกิดข้อผิดพลาดขณะคอมไพล์
// Error:
// fun <reified T> broken(): String = T::class.simpleName ?: "?"
// Must be inline:
inline fun <reified T> correct(): String = T::class.simpleName ?: "?"
fun main() {
println(correct<Double>()) // Double
}reified กับรีเฟลกชัน
ผสาน reified เข้ากับรีเฟลกชันเพื่อตรวจสอบพร็อพเพอร์ตีหรือคำกำกับของชนิดข้อมูลแบบไดนามิก โดยไม่ต้องเขียนพารามิเตอร์ Class ซ้ำซาก
inline fun <reified T : Any> properties(): List<String> =
T::class.members.map { it.name }
data class Point(val x: Int, val y: Int)
fun main() {
println(properties<Point>()) // [x, y, component1, component2, copy, equals, hashCode, toString]
}ภาคปฏิบัติ: ตัวค้นหาบริการที่ปลอดภัยด้านชนิดข้อมูล
ใช้ reified เพื่อสร้างตัวค้นหาบริการที่จับคู่ KClass กับอินสแตนซ์ สำหรับ DI แบบเบาโดยไม่ต้องใช้ตัวประมวลผลคำกำกับ
val registry = mutableMapOf<kotlin.reflect.KClass<*>, Any>()
inline fun <reified T : Any> register(instance: T) { registry[T::class] = instance }
@Suppress("UNCHECKED_CAST")
inline fun <reified T : Any> resolve(): T = registry[T::class] as T
class Logger { fun log(msg: String) = println("[LOG] $msg") }
fun main() {
register(Logger())
resolve<Logger>().log("Service located!")
}ข้อจำกัดของ reified
พารามิเตอร์ชนิดข้อมูลแบบ reified ไม่สามารถใช้ในบริบทที่ไม่ใช่ inline ไม่สามารถจัดเก็บชนิดข้อมูลไว้ใช้ภายหลัง และไม่สามารถส่งต่อให้ฟังก์ชันที่ไม่ใช่ inline ซึ่งต้องใช้ชนิดข้อมูลขณะรันไทม์ได้
inline fun <reified T> foo() {
val clazz = T::class // OK here
// bar(clazz) // must pass clazz explicitly to non-inline funs
println(clazz.simpleName)
}
fun bar(clazz: kotlin.reflect.KClass<*>) = println(clazz.simpleName)
fun main() { foo<String>() }ตรวจสอบความเข้าใจ
พารามิเตอร์ชนิดข้อมูลต้องมีเงื่อนไขใดจึงจะเป็น reified ได้
สรุปทบทวน
การลบชนิดข้อมูล จะลบข้อมูลชนิดข้อมูลเจเนอริกออกขณะรันไทม์ ส่วน reified บนฟังก์ชัน inline จะรักษาอาร์กิวเมนต์ชนิดข้อมูลไว้ที่จุดเรียกใช้ ทำให้ใช้ is, as, ::class และรีเฟลกชันกับ T ได้ โดยไม่ต้องส่งออบเจ็กต์ Class ด้วยตนเอง
คำถามที่พบบ่อย
บทเรียน “การลบชนิดและพารามิเตอร์ชนิด reified” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การลบชนิดและพารามิเตอร์ชนิด reified” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Kotlin Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การลบชนิดและพารามิเตอร์ชนิด reified”
ใช้ reified ร่วมกับฟังก์ชัน inline เพื่อเข้าถึงข้อมูลชนิดขณะรันไทม์ คุณปฏิบัติ Kotlin Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Kotlin Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Kotlin Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “การลบชนิดและพารามิเตอร์ชนิด reified” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Kotlin Academy นี้ได้ไหม
ได้ บทเรียน Kotlin Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ฟังก์ชัน Generic และข้อจำกัดชนิดด้วย where
- ความแปรผัน ณ จุดประกาศ: in และ out
- Star Projection และการใช้ *
- การลบชนิดและพารามิเตอร์ชนิด reified