0Pricing
Scala for Backend Engineering & Functional Programming · درس

الأنواع الجديدة

أغلفة آمنة من حيث النوع

الأنواع الجديدة درس مجاني في Scala for Backend Engineering & Functional Programming على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 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)

الأسئلة الشائعة

هل درس «الأنواع الجديدة» مجاني؟

نعم — نص درس «الأنواع الجديدة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Scala for Backend Engineering & Functional Programming، انتقل إلى CoddyKit PRO. تتضمن دورة Scala for Backend Engineering & Functional Programming 4 دروس في المجموع.

ماذا ستتعلم في «الأنواع الجديدة»؟

أغلفة آمنة من حيث النوع تتمرن على Scala for Backend Engineering & Functional Programming مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 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 يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. النمذجة باستخدام ADTs
  2. المنشئات الذكية
  3. الأنواع الجديدة
  4. تركيب المجالات
← العودة إلى Scala for Backend Engineering & Functional Programming