ชนิดข้อมูลใหม่
ตัวห่อหุ้มที่ปลอดภัยด้านชนิดข้อมูล
ชนิดข้อมูลใหม่ เป็นบทเรียน Scala for Backend Engineering & Functional Programming ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Scala for Backend Engineering & Functional Programming และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 4 บทเรียน
ตัวห่อหุ้มที่ปลอดภัยด้านชนิด
นิวไทป์คือชนิดที่แตกต่างซึ่งห่อหุ้มค่าพื้นฐานไว้หนึ่งค่า ช่วยป้องกันการสับสนระหว่างค่าที่มีรูปแทนพื้นฐานเดียวกัน เช่น UserId และ ProductId ที่เป็น Int ทั้งคู่
case class UserId(value: Int)
case class ProductId(value: Int)
object Main:
def main(args: Array[String]): Unit =
val u = UserId(1)
val p = ProductId(1)
println(u.value == p.value) // values equal, types differปัญหาการยึดติดกับชนิดพื้นฐาน
การยึดติดกับชนิดพื้นฐานคือการใช้ String และ Int มากเกินไปกับแนวคิดของโดเมน ทำให้เกิดเรื่องไร้เหตุผล เช่น ส่งอีเมลไปยังตำแหน่งที่ควรเป็นชื่อ นิวไทป์แก้ปัญหานี้ด้วยการให้แต่ละแนวคิดมีชนิดของตนเอง
case class Email(value: String)
case class City(value: String)
object Main:
def greet(c: City): String = s"Welcome to ${c.value}"
def main(args: Array[String]): Unit =
println(greet(City("Berlin")))นิวไทป์แบบคลาสกรณี
นิวไทป์ที่ง่ายที่สุดคือ case class ที่มีฟิลด์เดียว มันมอบความเท่าเทียมกัน เมธอด toString ที่อ่านง่าย และการจับคู่รูปแบบให้โดยอัตโนมัติ แต่มีต้นทุนการจัดสรรออบเจกต์หนึ่งรายการต่อค่า
case class OrderId(value: String)
object Main:
def main(args: Array[String]): Unit =
val id = OrderId("ORD-42")
println(id)
println(id.value)นิวไทป์แบบชนิดทึบแสง
หากต้องการไม่จัดสรรออบเจกต์ ให้สร้างนิวไทป์ด้วยชนิดทึบแสง ขณะทำงานจะมีพฤติกรรมเหมือนชนิดพื้นฐาน แต่ในเวลาคอมไพล์จะเป็นชนิดที่แตกต่างกัน
object Ids:
opaque type UserId = Int
def apply(i: Int): UserId = i
extension (u: UserId) def value: Int = u
object Main:
def main(args: Array[String]): Unit =
val u = Ids(7)
println(u.value)เพิ่มพฤติกรรมด้วยส่วนขยาย
เพิ่มการดำเนินการให้นิวไทป์ผ่านเมธอด extension โดยเปิดเผยเฉพาะสิ่งที่เหมาะสมกับแนวคิดของโดเมน
object Money:
opaque type Cents = Long
def apply(n: Long): Cents = n
extension (c: Cents)
def +(o: Cents): Cents = c + o
def toDollars: Double = c / 100.0
object Main:
def main(args: Array[String]): Unit =
val total = Money(250) + Money(750)
println(total.toDollars)นิวไทป์ในลายเซ็นฟังก์ชัน
นิวไทป์ทำให้ลายเซ็นอธิบายตัวเองได้และตรวจจับข้อผิดพลาดจากลำดับอาร์กิวเมนต์ตั้งแต่เวลาคอมไพล์ คุณจะสลับพารามิเตอร์ของนิวไทป์ต่างชนิดกันโดยไม่ตั้งใจไม่ได้
case class Width(value: Int)
case class Height(value: Int)
object Main:
def area(w: Width, h: Height): Int = w.value * h.value
def main(args: Array[String]): Unit =
println(area(Width(4), Height(5)))นิวไทป์และคอลเลกชัน
Map ที่ใช้คีย์เป็นนิวไทป์ชัดเจนและปลอดภัยกว่าการใช้ Int ดิบ ระบบชนิดจะป้องกันไม่ให้ใช้คีย์ผิดประเภท
case class UserId(value: Int)
object Main:
def main(args: Array[String]): Unit =
val names = Map(UserId(1) -> "Ada", UserId(2) -> "Bob")
println(names(UserId(2)))นิวไทป์ที่ผ่านการตรวจสอบ
ผสานนิวไทป์กับตัวสร้างอัจฉริยะเพื่อให้ตัวห่อหุ้มบังคับใช้เงื่อนไขคงที่ด้วย ในกรณีนี้ NonEmptyString จะไม่มีวันว่าง
case class NonEmptyString private (value: String)
object NonEmptyString:
def of(s: String): Option[NonEmptyString] =
if s.nonEmpty then Some(NonEmptyString(s)) else None
object Main:
def main(args: Array[String]): Unit =
println(NonEmptyString.of("hi"))
println(NonEmptyString.of(""))การเลือกตัวแทนข้อมูล
เลือกตามความต้องการของคุณ
- case class: ง่ายที่สุด จับคู่รูปแบบได้ และจัดสรรออบเจกต์
- opaque type: ไม่มีต้นทุน ไม่มีการห่อค่า เหมาะสำหรับเส้นทางที่ทำงานบ่อยและคอลเลกชันขนาดใหญ่
object Temp:
opaque type Kelvin = Double
def apply(d: Double): Kelvin = d
extension (k: Kelvin) def value: Double = k
object Main:
def main(args: Array[String]): Unit =
val readings = List(Temp(300.0), Temp(310.5))
println(readings.map(_.value).sum)ป้องกันการแปลงโดยไม่ตั้งใจ
นิวไทป์สองชนิดที่สร้างบนชนิดพื้นฐานเดียวกันจะไม่แปลงให้โดยอัตโนมัติ หากต้องการแปลงระหว่างกัน คุณต้องเขียนฟังก์ชันอย่างชัดเจนเพื่อบันทึกเจตนา
case class Meters(value: Double)
case class Feet(value: Double)
object Main:
def toFeet(m: Meters): Feet = Feet(m.value * 3.281)
def main(args: Array[String]): Unit =
println(toFeet(Meters(2.0)))ควรใช้นิวไทป์เมื่อใด
เลือกใช้นิวไทป์เมื่อใดก็ตามที่ชนิดพื้นฐานมีความหมายในโดเมน
- ตัวระบุ หน่วย และสตริงที่มีรูปแบบกำหนด
- ใช้ case class เพื่อความเรียบง่าย และ opaque type เพื่อประสิทธิภาพ
- เพิ่มตัวสร้างอัจฉริยะเมื่อมีเงื่อนไขคงที่
object Domain:
opaque type Sku = String
def of(s: String): Option[Sku] =
if s.startsWith("SKU-") then Some(s) else None
extension (k: Sku) def raw: String = k
object Main:
def main(args: Array[String]): Unit =
println(Domain.of("SKU-9").map(_.raw))ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจของคุณเกี่ยวกับนิวไทป์
สรุปทบทวน
คุณได้เรียนรู้นิวไทป์
- นิวไทป์ห่อหุ้มค่าพื้นฐานหนึ่งค่าไว้ในชนิดที่แตกต่าง
- ช่วยแก้ปัญหาการยึดติดกับชนิดพื้นฐานและป้องกันการสลับอาร์กิวเมนต์
- ใช้
case classเพื่อความเรียบง่าย และopaque typeเพื่อไม่มีต้นทุน - เพิ่มตัวสร้างอัจฉริยะสำหรับตัวห่อหุ้มที่ผ่านการตรวจสอบ
- การแปลงระหว่างนิวไทป์ต้องระบุอย่างชัดเจนเสมอ
object Ids:
opaque type AccountId = Long
def apply(n: Long): AccountId = n
extension (a: AccountId) def value: Long = a
object Main:
def main(args: Array[String]): Unit =
val acc = Ids(1001L)
println(acc.value)คำถามที่พบบ่อย
บทเรียน “ชนิดข้อมูลใหม่” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ชนิดข้อมูลใหม่” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Scala for Backend Engineering & Functional Programming ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ชนิดข้อมูลใหม่”
ตัวห่อหุ้มที่ปลอดภัยด้านชนิดข้อมูล คุณปฏิบัติ Scala for Backend Engineering & Functional Programming ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Scala for Backend Engineering & Functional Programming หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Scala for Backend Engineering & Functional Programming บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “ชนิดข้อมูลใหม่” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Scala for Backend Engineering & Functional Programming นี้ได้ไหม
ได้ บทเรียน Scala for Backend Engineering & Functional Programming ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การสร้างแบบจำลองด้วย ADT
- ตัวสร้างอัจฉริยะ
- ชนิดข้อมูลใหม่
- การประกอบโดเมน