Typealias เป็นกลไก Kotlin สำหรับสร้างชื่อทางเลือกสำหรับชนิดที่มีอยู่แล้ว คำสำคัญ typealias ช่วยให้คุณแทนที่การประกาศชนิดที่ซับซ้อนด้วยนามแฝงที่สั้นและชัดเจนโดยไม่ต้องสร้างชนิดใหม่ ตาม เอกสาร Kotlin (2026) typealias ช่วยปรับปรุงการอ่านโค้ด โดยเฉพาะในลายเซ็นเชอร์ของฟังก์ชันที่มีชนิดฟังก์ชัน Typealias ทำให้โค้ดสามารถอธิบายตัวเองได้โดยการแทนที่การประกาศที่ยาวเอือด้วยชนิดที่มีชื่อชัดเจน
ข้อเรียนรู้สำคัญ
Typealias (นามแฝงชนิด) เป็นการประกาศที่แนะนำชื่อทางเลือกสำหรับชนิดที่มีอยู่แล้ว ไวยากรณ์: typealias ชื่อใหม่ = ชนิดที่มีอยู่ หลังจากการประกาศ สามารถใช้ชื่อใหม่ได้ทุกที่ที่คาดหวังชนิดที่มีอยู่ — คอมไพเลอร์ถือว่าเป็นชนิดเดียวกัน ในระดับไบต์โค้ด typealias ไม่ทิ้งรอยเว้น: ข้อมูลนามแฝงทั้งหมดจะถูกลบในขณะแปลง
จุดประสงค์หลักของ typealias คือการปรับปรุง การอ่านโค้ด แทนที่จะใช้ลายเซ็นเชอร์ยาว fun process(callback: (Result) -> Unit) คุณสามารถเขียน typealias Callback = (Result) -> Unit และใช้ Callback เป็นชนิดพารามิเตอร์ ซึ่งมีประโยชน์โดยเฉพาะเมื่อชนิดฟังก์ชันเดียวกันถูกทำซ้ำในหลายจุดในโค้ด: นามแฝงทำหน้าที่เป็นจุดกำหนดเดียวและบันทึกวัตถุประสงค์ของชนิด
Typealias ไม่สร้างชนิดใหม่ — เป็น เพียงคำพ้อง ตัวแปรชนิด Callback และ (Result) -> Unit สามารถแลกเปลี่ยนกันได้อย่างสมบูรณ์ คอมไพเลอร์จะไม่สร้างข้อผิดพลาดหากมอบ lambda โดยตรงไปยังฟังก์ชันที่คาดหวัง Callback ทำให้ typealias แตกต่างจาก inline class (value class) ซึ่งสร้างชนิดห่อหุ้มใหม่พร้อมการตรวจสอบขณะแปลง Typealias คือการตั้งชื่อใหม่ ไม่ใช่การห่อหุ้ม
กรณีใช้งานที่พบบ่อยที่สุดของ typealias ใน Kotlin คือ ชนิดฟังก์ชัน ลายเซ็นเชอร์ยาวเช่น (Int, String) -> Boolean หรือ (List
// Without typealias
fun findUsers(
filter: (List<User>) -> List<User>
): List<User>
// With typealias
typealias UserFilter = (List<User>) -> List<User>
fun findUsers(filter: UserFilter): List<User>
// Usage in class
typealias OnClickListener = (View) -> Unit
class Button {
var onClick: OnClickListener = {}
}
ในตัวอย่าง typealias UserFilter ซ่อนชนิดฟังก์ชันที่ซับซ้อน (List
Typealias รองรับพารามิเตอร์ทั่วไป ทำให้มันมีความยืดหยุ่นยิ่งขึ้น คุณสามารถกำหนด typealias Mapper
// Generic typealias
typealias Mapper<T, R> = (T) -> R
typealias Provider<T> = () -> T
typealias ListTransformer<T> = (List<T>) -> List<T>
fun processNumbers(mapper: Mapper<Int, String>) {
// mapper type is (Int) -> String
}
fun main() {
val config: Provider<String> = { "default config" }
val reverse: ListTransformer<Int> = { it.reversed() }
}
ในรายการ Mapper
คลาสที่ซ้อนกันและชนิดที่มีพารามิเตอร์ยาวเป็นอีกพื้นที่ที่ typealias ทำให้โค้ดง่ายขึ้นอย่างมาก หากคลาสอยู่ลึกในลำดับชั้นสมเทษ (Outer.Inner.Nested) การอ้างถึงชื่อเต็มจะทำให้โค้ดรกร้าย Typealias ย่อการเข้าถึงดังกล่าวและทำให้อ่านง่ายขึ้น โดยเฉพาะอย่างยิ่งสำหรับคลาสจากไลบรารีของบุคคลที่สามที่มีชื่อยาว
// Alias for nested class
class NetworkResponse {
class Error(val code: Int, val message: String)
}
typealias NetworkError = NetworkResponse.Error
// Alias for long library type
typealias UserId = Long
typealias JsonMap = Map<String, Any?>
fun process(error: NetworkError) {
println("${error.code}: ${error.message}")
}
fun parseJson(data: JsonMap): UserId {
return data["id"] as? Long ?: 0L
}
ในตัวอย่าง NetworkError เป็นนามแฝงสำหรับคลาสซ้อนกัน NetworkResponse.Error โดยการนำเข้า typealias คุณสามารถใช้ NetworkError เป็นชนิดปกติโดยไม่ต้องเปิดเผยลำดับชั้นสมเทษ JsonMap บันทึกว่าแผนที่แสดงถึงวัตถุ JSON UserId ชี้แจงวัตถุประสงค์ของ Long ในบริบทเฉพาะ — ผู้อ่านเข้าใจทันทีว่านี้คือตัวระบุผู้ใช้ ไม่ใช่ตัวเลขที่เรียกได้ตามอำเภอ อย่างไรก็ตาม typealias ไม่ป้องกันการส่ง Long ทั่วไปไปยังที่ที่คาดหวัง UserId — สำหรับเรื่องนั้นต้องใช้ value class
Typealias และ inline class (value class) แก้ปัญหาที่แตกต่างกัน แม้ว่าทั้งสองจะแนะนำชื่อใหม่สำหรับชนิดก็ตาม Typealias เป็นเพียงคำพ้อง: ตัวแปรชนิด UserId = Long รับ Long ใดๆ โดยไม่มีการตรวจสอบ Inline class ห่อค่าในชนิดใหม่ที่ถูกตรวจสอบในขณะแปลง: ไม่สามารถส่ง Long ทั่วไปไปยังที่ที่คาดหวัง inline class UserId โดยไม่มีการแปลงอย่างชัดเจน
| ลักษณะ | Typealias | Inline class |
|---|---|---|
| ชนิดใหม่ | ไม่ — คำพ้องของต้นฉบับ | ใช่ — ชนิดใหม่พร้อมการตรวจสอบ |
| ประสิทธิภาพ | ศูนย์ — ถูกลบอย่างสมบูรณ์ | ศูนย์ — ตัวห่อถูกลบออกในไบต์โค้ด |
| การสืบทอด | ไม่ | ไม่ (คลาสจบ) |
| เมธอดของตัวเอง | ไม่ | ใช่ — สามารถประกาศฟังก์ชันได้ |
| ความปลอดภัยของชนิด | ไม่ — แลกเปลี่ยนกับต้นฉบับได้ | ใช่ — คอมไพเลอร์แยกแยะชนิด |
ตารางแสดงความแตกต่างระหว่างกลไกทั้งสอง Typealias เหมาะสำหรับชื่อที่กระชับและการบันทึกโค้ดเมื่อไม่ต้องการการพิมพ์ที่เคร่งครัด Inline class ผ่านคำสำคัญ value class (เดิมคือ inline class) จำเป็นเมื่อจำเป็นต้องแยกแยะค่าที่แตกต่างกันทางความหมายของชนิดเดิมเดียวกัน ตัวอย่างเช่น UserId และ OrderId ล้วนเป็น Long แต่การส่งตัวหนึ่งไปยังที่ที่คาดหวังอีกตัวเป็นข้อผิดพลาดทางตรรกะที่ value class ป้องกันได้ในขณะแปลง
คำถามที่พบบ่อย
Import alias (import com.example.LongName as Short) ทำงานในระดับการนำเข้า — จะย่อชื่อเฉพาะในไฟล์ปัจจุบัน Typealias ประกาศนามแฝงทั่วโลกที่สามารถใช้ได้ทั่งโปรเจคหลังจากการนำเข้า
ได้ typealias รองรับนิยามแบบเรียกซ้ำสำหรับชนิดฟังก์ชัน แต่ต้องระมัดระวัง: typealias Rec
ไม่ typealias ถูกลบอย่างสมบูรณ์ในขณะแปลง ชนิดต้นฉบับจะถูกใช้ในระดับไบต์โค้ดและรันไทมโดยไม่มีตัวห่อ ประสิทธิภาพเหมือนกับการใช้ชนิดต้นฉบับโดยตรง
Typealias สามารถอ้างถึง typealias อื่นได้ — เรียกว่าสายโส้ของนามแฝง ความลึกของสายโส้ไม่มีข้อจำกัดอย่างเป็นทางการ แต่เพื่อความสามารถอ่านได้ ไม่ควรเกิน 2–3 ระดับ คอมไพเลอร์จะแก้ไขสายโส้อย่างสมบูรณ์ในขั้นตอนการวิเคราะห์
ไม่ typealias เป็นการประกาศระดับบนสุดหรือสมาชิกของคลาส/วัตถุ ไม่สามารถประกาศ typealias ภายในฟังก์ชัน สำหรับการย่อชนิดในท้องถิ่น ใช้ import alias ภายในไฟล์หรือวาง typealias ไว้ในระดับโมดูล
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม