Kotlin Academy · บทเรียน

sealed class กับ sealed interface: ควรใช้แบบใด

ทำความเข้าใจความแตกต่างระหว่าง sealed class และ interface ใน Kotlin

บทเรียน 1 จาก 413 ขั้นตอน

sealed class กับ sealed interface: ควรใช้แบบใด เป็นบทเรียน Kotlin Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Kotlin Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน

ชนิดแบบปิดผนึกใน Kotlin

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

พื้นฐานคลาสแบบปิดผนึก

คลาสแบบปิดผนึกจะจำกัดการสืบทอดคลาสย่อยให้อยู่ในแพ็กเกจเดียวกัน (Kotlin 1.5 ขึ้นไป) หรืออยู่ในไฟล์เดียวกัน
sealed class Shape
class Circle(val radius: Double) : Shape()
class Rectangle(val w: Double, val h: Double) : Shape()
object Unknown : Shape()

อินเทอร์เฟซแบบปิดผนึก: ยืดหยุ่นกว่า

อินเทอร์เฟซแบบปิดผนึกอนุญาตให้ชนิดย่อยขยายคลาสอื่นและนำอินเทอร์เฟซอื่นไปใช้ได้พร้อมกัน ซึ่งคลาสแบบปิดผนึกทำไม่ได้
sealed interface Result<out T>
data class Success<T>(val value: T) : Result<T>
data class Error(val ex: Exception) : Result<Nothing>

ความแตกต่างสำคัญ

คลาสแบบปิดผนึก: คลาสย่อยมีตัวสร้างและสถานะได้ อินเทอร์เฟซแบบปิดผนึก: ชนิดย่อยสามารถขยายคลาสใดก็ได้ โปรดใช้อินเทอร์เฟซแบบปิดผนึกเมื่อต้องการความยืดหยุ่นมากขึ้น
// sealed class subtype extends another class:
sealed interface Command
class MoveCommand(val dx: Int, val dy: Int) : Command, Serializable
class ResizeCommand(val scale: Double) : Command, Cloneable

นิพจน์เงื่อนไขที่ครอบคลุมทุกกรณี: ไม่ต้องใช้กรณีอื่น

เมื่อครอบคลุมชนิดย่อยแบบปิดผนึกทั้งหมดแล้ว นิพจน์เงื่อนไขจะครอบคลุมครบถ้วน จึงไม่ต้องใช้กรณีอื่น และคอมไพเลอร์จะบังคับให้ครอบคลุมทุกกรณี
fun area(shape: Shape): Double = when (shape) {
    is Circle -> Math.PI * shape.radius * shape.radius
    is Rectangle -> shape.w * shape.h
}  // no 'else' — compiler guarantees completeness

การเพิ่มชนิดย่อยทำให้นิพจน์เงื่อนไขเดิมใช้ไม่ได้

เพิ่มชนิดย่อยแบบปิดผนึกใหม่ แล้วนิพจน์เงื่อนไขเดิมจะคอมไพล์ไม่ผ่านจนกว่าจะปรับปรุง นี่คือประโยชน์หลัก
// Add Triangle to Shape:
class Triangle(val base: Double, val height: Double) : Shape()
// Now the area() function above won't compile until
// a Triangle branch is added — safety net!

คลาสแบบปิดผนึกที่มีคุณสมบัติร่วม

ประกาศคุณสมบัติที่ใช้ร่วมกันไว้ในคลาสแบบปิดผนึก
sealed class NetworkResult {
    abstract val timestamp: Long
}
data class SuccessResult(val data: String, override val timestamp: Long) : NetworkResult()
data class FailureResult(val error: String, override val timestamp: Long) : NetworkResult()

ชนิดแบบปิดผนึกซ้อนกัน

ชนิดย่อยแบบปิดผนึกสามารถเป็นชนิดแบบปิดผนึกต่อได้ เพื่อสร้างลำดับชั้นหลายระดับ
sealed interface UiState
object Loading : UiState
sealed interface Loaded : UiState
data class Content(val items: List<String>) : Loaded
data class Empty(val hint: String) : Loaded
data class Failure(val error: String) : UiState

ชนิดย่อย object สำหรับรูปแบบที่ไม่มีสถานะ

ใช้ object สำหรับชนิดย่อยแบบปิดผนึกที่ไม่มีสถานะ
sealed class Direction
object North : Direction()
object South : Direction()
object East : Direction()
object West : Direction()

fun move(d: Direction) = when (d) {
    North -> y++
    South -> y--
    East -> x++
    West -> x--
}

ใช้คลาสข้อมูลและ object ร่วมกับชนิดแบบปิดผนึก

ผสมคลาสข้อมูล (สำหรับชนิดย่อยที่มีสถานะ) และ object (สำหรับอินสแตนซ์เดี่ยว) ไว้ภายใต้ชนิดแบบปิดผนึก
sealed class LoadState
object Idle : LoadState()
object Loading : LoadState()
data class Success(val count: Int) : LoadState()
data class Error(val msg: String) : LoadState()

เมื่อใดควรเลือกคลาสแบบปิดผนึกกับอินเทอร์เฟซแบบปิดผนึก

ใช้คลาสแบบปิดผนึกเมื่อชนิดย่อยทั้งหมดมีสถานะร่วมกัน ใช้อินเทอร์เฟซแบบปิดผนึกเมื่อชนิดย่อยจำเป็นต้องขยายคลาสพื้นฐานที่แตกต่างกันหรือนำอินเทอร์เฟซอื่นไปใช้

ตรวจสอบอย่างรวดเร็ว

อินเทอร์เฟซแบบปิดผนึกมีข้อได้เปรียบเหนือคลาสแบบปิดผนึกอย่างไร

ทบทวน

คลาสหรืออินเทอร์เฟซแบบปิดผนึกจะจำกัดลำดับชั้นไว้เฉพาะชนิดที่ทราบแน่ชัด นิพจน์เงื่อนไขบนชนิดแบบปิดผนึกจะครอบคลุมครบถ้วน จึงไม่ต้องใช้กรณีอื่น อินเทอร์เฟซแบบปิดผนึกอนุญาตให้ชนิดย่อยขยายคลาสอื่นได้ ใช้คลาสข้อมูลสำหรับชนิดย่อยที่มีสถานะ และใช้ object สำหรับชนิดย่อยที่ไม่มีสถานะ
เริ่มต้นได้ฟรี

เรียนรู้ Kotlin ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
51
บทเรียน
203

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

บทเรียน “sealed class กับ sealed interface: ควรใช้แบบใด” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “sealed class กับ sealed interface: ควรใช้แบบใด” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Kotlin Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “sealed class กับ sealed interface: ควรใช้แบบใด”

ทำความเข้าใจความแตกต่างระหว่าง sealed class และ interface ใน Kotlin คุณปฏิบัติ Kotlin Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Kotlin Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Kotlin Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “sealed class กับ sealed interface: ควรใช้แบบใด” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Kotlin Academy นี้ได้ไหม

ได้ บทเรียน Kotlin Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. sealed class กับ sealed interface: ควรใช้แบบใด
  2. when แบบครอบคลุมทุกกรณีกับลำดับชั้น Sealed
  3. จำลองสถานะ UI ด้วย Sealed Class
  4. การซ้อนและรวมลำดับชั้น Sealed
← กลับไปที่ Kotlin Academy