Scala for Backend Engineering & Functional Programming · บทเรียน

การสร้างแบบจำลองด้วย ADT

ทำให้สถานะที่ไม่ถูกต้องไม่สามารถแทนค่าได้

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

การสร้างแบบจำลองด้วย ADT เป็นบทเรียน Scala for Backend Engineering & Functional Programming ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Scala for Backend Engineering & Functional Programming และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 4 บทเรียน

ชนิดข้อมูลพีชคณิต

ชนิดข้อมูลพีชคณิต (ADT) เป็นรากฐานของการสร้างแบบจำลองโดเมนเชิงฟังก์ชัน โดยรวมชนิดผลคูณ (AND) และชนิดผลรวม (OR) เพื่ออธิบายข้อมูลอย่างแม่นยำ

  • ผลคูณ: ระเบียนที่มีหลายฟิลด์
  • ผลรวม: ทางเลือกจากหลายรูปแบบ
case class Point(x: Int, y: Int) // product type

object Main:
  def main(args: Array[String]): Unit =
    println(Point(1, 2))

ชนิดผลคูณ

ชนิดผลคูณรวมค่าหลายค่าเข้าด้วยกัน ใน Scala case class เป็นผลคูณ กล่าวคืออินสแตนซ์หนึ่งรายการมีฟิลด์ทั้งหมดอยู่พร้อมกัน

case class User(name: String, age: Int)

object Main:
  def main(args: Array[String]): Unit =
    val u = User("Ada", 36)
    println(u.name)
    println(u.age)

ชนิดผลรวม

ชนิดผลรวมคือค่าที่เป็นหนึ่งในหลายรูปแบบอย่างแน่นอน enum ของ Scala 3 แสดงแนวคิดนี้ได้โดยตรง

enum PaymentMethod:
  case Cash
  case Card(number: String)
  case Crypto(wallet: String)

object Main:
  def main(args: Array[String]): Unit =
    val p: PaymentMethod = PaymentMethod.Card("1234")
    println(p)

ทำให้สถานะที่ผิดกฎหมายไม่สามารถแทนค่าได้

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

enum Connection:
  case Disconnected
  case Connected(sessionId: String)

object Main:
  def main(args: Array[String]): Unit =
    // No way to have a sessionId while Disconnected
    val c: Connection = Connection.Connected("abc")
    println(c)

การออกแบบที่ไม่ดีเทียบกับการออกแบบที่ดี

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

  • ไม่ดี: case class Conn(connected: Boolean, sessionId: String) อนุญาตให้ connected=false พร้อมกับมี sessionId
  • ดี: ชนิดผลรวมผูกฟิลด์เข้ากับสถานะที่ถูกต้อง
enum Door:
  case Open
  case Closed
  case Locked(key: String)

object Main:
  def main(args: Array[String]): Unit =
    val d: Door = Door.Locked("k1")
    println(d)

การรวมชนิดผลคูณและผลรวม

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

case class Address(city: String, zip: String)

enum Contact:
  case Email(value: String)
  case Postal(address: Address)

object Main:
  def main(args: Array[String]): Unit =
    val c: Contact = Contact.Postal(Address("Paris", "75001"))
    println(c)

การจับคู่รูปแบบกับ ADT

คุณใช้งาน ADT ด้วยการจับคู่รูปแบบ เนื่องจากชนิดนี้ปิดและมีรูปแบบที่ทราบแน่นอน คอมไพเลอร์จะแจ้งเตือนหากคุณพลาดรูปแบบใดไป

enum Shape:
  case Circle(r: Double)
  case Rect(w: Double, h: Double)

object Main:
  def area(s: Shape): Double = s match
    case Shape.Circle(r)  => 3.14159 * r * r
    case Shape.Rect(w, h) => w * h

  def main(args: Array[String]): Unit =
    println(area(Shape.Rect(2, 3)))

ADT แบบเรียกซ้ำ

ADT สามารถอ้างอิงตัวเองได้ จึงใช้จำลองต้นไม้ รายการ และนิพจน์ได้อย่างเป็นธรรมชาติ

enum Expr:
  case Num(value: Int)
  case Add(left: Expr, right: Expr)

object Main:
  def eval(e: Expr): Int = e match
    case Expr.Num(v)    => v
    case Expr.Add(l, r) => eval(l) + eval(r)

  def main(args: Array[String]): Unit =
    val e = Expr.Add(Expr.Num(2), Expr.Num(3))
    println(eval(e))

การแสดงความเป็นตัวเลือกด้วย Option

ใช้ Option แทน null เพื่อจำลองฟิลด์ที่อาจไม่มีค่า ชนิดนี้ทำให้การไม่มีค่าชัดเจนและบังคับให้จัดการกรณีดังกล่าว

case class Profile(name: String, nickname: Option[String])

object Main:
  def main(args: Array[String]): Unit =
    val p = Profile("Grace", None)
    println(p.nickname.getOrElse("(none)"))

การจำลองปริมาณอย่างแม่นยำ

แทนที่การยึดติดกับชนิดพื้นฐาน แทนที่จะใช้ Int และ String ดิบ ให้ห่อหุ้มปริมาณที่มีความหมาย เพื่อให้ชนิดบอกเจตนาและป้องกันการสับสน

case class Quantity(value: Int)
case class Price(cents: Long)
case class LineItem(qty: Quantity, price: Price)

object Main:
  def main(args: Array[String]): Unit =
    val item = LineItem(Quantity(3), Price(500))
    println(item)

เหตุใด ADT จึงสำคัญ

ADT ช่วยให้โค้ดถูกต้องและชัดเจน

  • ไม่สามารถสร้างสถานะที่ไม่ถูกต้องได้
  • การจับคู่ที่ครอบคลุมทั้งหมดตรวจพบกรณีที่พลาดตั้งแต่เวลาคอมไพล์
  • โครงสร้างข้อมูลอธิบายโดเมนได้ในตัว
enum OrderStatus:
  case Pending
  case Shipped(tracking: String)
  case Delivered(at: Long)

object Main:
  def main(args: Array[String]): Unit =
    val s: OrderStatus = OrderStatus.Shipped("TRK1")
    println(s)

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ทดสอบความเข้าใจของคุณเกี่ยวกับการสร้างแบบจำลองด้วย ADT

สรุปทบทวน

คุณได้เรียนรู้การสร้างแบบจำลองโดเมนด้วย ADT

  • ชนิดผลคูณ (case class) รวมฟิลด์ด้วย AND
  • ชนิดผลรวม (enum) นำเสนอทางเลือกด้วย OR
  • ซ้อนชนิดเหล่านี้เพื่อจำลองโดเมนที่ซับซ้อนและโครงสร้างแบบเรียกซ้ำ
  • ใช้ Option แทน null
  • ออกแบบให้ไม่สามารถแทนค่าสถานะที่ผิดกฎหมายได้
enum Event:
  case Created(id: Int)
  case Deleted(id: Int, reason: String)

object Main:
  def describe(e: Event): String = e match
    case Event.Created(id)         => s"created $id"
    case Event.Deleted(id, reason) => s"deleted $id: $reason"

  def main(args: Array[String]): Unit =
    println(describe(Event.Deleted(1, "spam")))
เริ่มต้นได้ฟรี

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

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

คอร์ส
39
บทเรียน
143

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

บทเรียน “การสร้างแบบจำลองด้วย ADT” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การสร้างแบบจำลองด้วย ADT” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Scala for Backend Engineering & Functional Programming ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การสร้างแบบจำลองด้วย ADT”

ทำให้สถานะที่ไม่ถูกต้องไม่สามารถแทนค่าได้ คุณปฏิบัติ Scala for Backend Engineering & Functional Programming ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Scala for Backend Engineering & Functional Programming หรือไม่

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

บทเรียน “การสร้างแบบจำลองด้วย ADT” ใช้เวลานานแค่ไหน

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

ฉันเขียนและรันโค้ดในบทเรียน Scala for Backend Engineering & Functional Programming นี้ได้ไหม

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

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

  1. การสร้างแบบจำลองด้วย ADT
  2. ตัวสร้างอัจฉริยะ
  3. ชนิดข้อมูลใหม่
  4. การประกอบโดเมน
← กลับไปที่ Scala for Backend Engineering & Functional Programming