การสร้างแบบจำลองด้วย ADT
ทำให้สถานะที่ไม่ถูกต้องไม่สามารถแทนค่าได้
การสร้างแบบจำลองด้วย 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การสร้างแบบจำลองด้วย ADT
- ตัวสร้างอัจฉริยะ
- ชนิดข้อมูลใหม่
- การประกอบโดเมน