ความแปรผัน ณ จุดประกาศ
in และ out
ความแปรผัน ณ จุดประกาศ เป็นบทเรียน Kotlin Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Kotlin Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน
ปัญหาของความแปรผัน
List<String> เป็นชนิดหนึ่งของ List<Any> หรือไม่ บางครั้งใช่ และบางครั้งไม่ใช่ ความแปรผันอธิบายว่าชนิดข้อมูลเจเนอริกมีความสัมพันธ์กันอย่างไรเมื่อพารามิเตอร์ชนิดข้อมูลของทั้งสองมีความสัมพันธ์กัน Kotlin ใช้ out และ in เพื่อแสดงความสัมพันธ์นี้
ไม่แปรผันเป็นค่าเริ่มต้น
โดยค่าเริ่มต้น เจเนอริกส์จะ ไม่แปรผัน: Box<String> ไม่ใช่ Box<Any> แม้ว่า String จะเป็นชนิดข้อมูลย่อยของ Any ก็ตาม วิธีนี้ช่วยป้องกันการดำเนินการที่ไม่ปลอดภัย
class Box<T>(val value: T)
fun main() {
val strBox = Box("hi")
// val anyBox: Box<Any> = strBox // would not compile
println(strBox.value)
}ความแปรผันร่วมด้วย out
การกำหนดพารามิเตอร์ชนิดข้อมูลเป็น out จะทำให้เกิด ความแปรผันร่วม: Producer<String> จะกลายเป็นชนิดข้อมูลย่อยของ Producer<Any> ชนิดข้อมูลนี้สามารถปรากฏได้เฉพาะในตำแหน่ง ผลลัพธ์ เช่น ชนิดข้อมูลที่ส่งคืน
class Producer<out T>(private val item: T) {
fun produce(): T = item
}
fun main() {
val strProducer: Producer<String> = Producer("hello")
val anyProducer: Producer<Any> = strProducer
println(anyProducer.produce())
}เหตุใด out จึงปลอดภัย
หากคลาสสร้างหรือส่งคืน T เพียงอย่างเดียวและไม่รับค่าเข้ามา การมอง Producer<String> เป็น Producer<Any> ก็ปลอดภัย เพราะ String ทุกค่าที่ส่งคืนมาก็เป็น Any เช่นกัน
out ในไลบรารีมาตรฐาน
List<out E> แบบอ่านอย่างเดียวของ Kotlin มีความแปรผันร่วม นี่จึงเป็นเหตุผลที่สามารถใช้ List<String> ในตำแหน่งที่ต้องการ List<Any> ได้
fun printAll(items: List<Any>) {
items.forEach { println(it) }
}
fun main() {
val names: List<String> = listOf("Ann", "Bob")
printAll(names)
}ความแปรผันย้อนด้วย in
การกำหนดพารามิเตอร์ชนิดข้อมูลเป็น in จะทำให้เกิด ความแปรผันย้อน: Consumer<Any> จะกลายเป็นชนิดข้อมูลย่อยของ Consumer<String> ชนิดข้อมูลนี้สามารถปรากฏได้เฉพาะในตำแหน่ง ข้อมูลเข้า เช่น พารามิเตอร์
class Consumer<in T> {
fun consume(item: T) {
println("Consumed $item")
}
}
fun main() {
val anyConsumer: Consumer<Any> = Consumer()
val strConsumer: Consumer<String> = anyConsumer
strConsumer.consume("hi")
}เหตุใด in จึงปลอดภัย
ผู้รับข้อมูลที่รับ Any ได้ย่อมรับ String ได้แน่นอน ดังนั้น Consumer<Any> จึงสามารถใช้แทนที่ใดก็ตามที่ต้องการ Consumer<String> ได้
หลักช่วยจำผู้ผลิตและผู้รับข้อมูล
โปรดจำหลักว่า Producer ขยาย และ Consumer อยู่เหนือกว่า หรือในคำศัพท์ของ Kotlin คือ out สำหรับผู้ผลิต ซึ่งเป็นข้อมูลออก และ in สำหรับผู้รับข้อมูล ซึ่งเป็นข้อมูลเข้า ชนิดข้อมูลที่ส่งออก T เพียงอย่างเดียวให้ใช้ out ส่วนชนิดข้อมูลที่รับ T เข้าเพียงอย่างเดียวให้ใช้ in
การใช้ in และ out ร่วมกัน
พารามิเตอร์ชนิดข้อมูลที่ใช้ทั้งกับข้อมูลเข้าและข้อมูลออก เช่น ในลิสต์ที่เปลี่ยนแปลงได้ จะต้องคงเป็นชนิดที่ไม่แปรผัน ชนิดข้อมูลฟังก์ชันแสดงให้เห็นทั้งสองแบบ: พารามิเตอร์เป็น in ส่วนค่าที่ส่งคืนเป็น out
fun main() {
val f: (Number) -> Int = { it.toInt() }
val g: (Int) -> Number = f
println(g(3.0.let { Number::class; 5 }))
}ความแปรผัน ณ จุดประกาศหมายถึงประกาศครั้งเดียว
ความแปรผัน ณ จุดประกาศจะประกาศเพียงครั้งเดียวที่ตัวคลาสด้วย in/out จากนั้นการใช้คลาสทุกครั้งจะได้รับความแปรผันโดยอัตโนมัติ ต่างจาก Java ที่ต้องเขียนไวลด์การ์ดซ้ำทุกครั้งที่ใช้งาน
การเลือก in หรือ out
ให้ถามว่า คลาสนี้สร้างหรือส่งคืน T เพียงอย่างเดียวหรือไม่ หากใช่ให้ใช้ out รับ T เพียงอย่างเดียวหรือไม่ หากใช่ให้ใช้ in หรือทำทั้งสองอย่าง หากทำทั้งสองอย่างให้ปล่อยไว้โดยไม่แปรผัน การเลือกตัวปรับแต่งให้ตรงกับบทบาทจะทำให้ชนิดข้อมูลเจเนอริกยืดหยุ่นและปลอดภัย
ตรวจสอบอย่างรวดเร็ว
ตัวปรับแต่ง out แสดงถึงอะไร
ทบทวน
โดยค่าเริ่มต้น เจเนอริกส์จะไม่แปรผัน ใช้ out สำหรับความแปรผันร่วมเมื่อชนิดข้อมูลสร้างหรือส่งคืนค่าเพียงอย่างเดียว และใช้ in สำหรับความแปรผันย้อนเมื่อชนิดข้อมูลรับค่าเพียงอย่างเดียว โปรดจำว่าผู้ผลิตใช้ out และผู้รับข้อมูลใช้ in ต่อไปคุณจะใช้ความแปรผัน ณ จุดใช้งานด้วยการฉายชนิดข้อมูล
คำถามที่พบบ่อย
บทเรียน “ความแปรผัน ณ จุดประกาศ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ความแปรผัน ณ จุดประกาศ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Kotlin Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ความแปรผัน ณ จุดประกาศ”
in และ out คุณปฏิบัติ Kotlin Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Kotlin Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Kotlin Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “ความแปรผัน ณ จุดประกาศ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Kotlin Academy นี้ได้ไหม
ได้ บทเรียน Kotlin Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ฟังก์ชันและคลาสแบบเจเนอริก
- ความแปรผัน ณ จุดประกาศ
- ความแปรผัน ณ จุดใช้งาน
- ข้อจำกัดของเจเนอริก