الأنواع المعتمة
تجريدات بلا تكلفة إضافية
الأنواع المعتمة درس مجاني في 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 دروس في المجموع.
ما الأنواع المعتمة؟
الأنواع المعتمة ميزة في Scala 3 لإنشاء تجريدات بلا تكلفة. فهي تمنح نوعًا مميزًا وقت الترجمة، لكنها تُترجم إلى النوع الأساسي دون تغليف وقت التشغيل.
- أمان نوع يضاهي صنف التغليف.
- لا تكلفة تخصيص إضافية.
object Distances:
opaque type Meters = Double
object Main:
def main(args: Array[String]): Unit =
println("Opaque types compile to their underlying type")تعريف نوع معتم
عرّف نوعًا معتمًا داخل كائن أو صنف. وخارج ذلك النطاق، يُعامل Meters وDouble على أنهما نوعان مختلفان.
object Distances:
opaque type Meters = Double
def meters(d: Double): Meters = d
def toDouble(m: Meters): Double = m
object Main:
def main(args: Array[String]): Unit =
val d = Distances.meters(5.0)
println(Distances.toDouble(d))حدود التعتيم
داخل النطاق الذي عُرّف فيه النوع، يكون النوع المعتم والنوع الأساسي قابلين للتبادل. أما خارجه، فلا يظهر إلا النوع المعتم، لذلك لا يمكنك تمرير Double خام بالخطأ حيث تكون Meters مطلوبة.
object Distances:
opaque type Meters = Double
def apply(d: Double): Meters = d
def show(m: Meters): String = s"$m m"
object Main:
def main(args: Array[String]): Unit =
val m = Distances(10.0)
println(Distances.show(m))إضافة Extension Methods
امنح الأنواع المعتمة سلوكًا باستخدام extension methods المعرّفة في النطاق نفسه. ويحصل المستدعون على عمليات مريحة دون كشف النوع الأساسي.
object Distances:
opaque type Meters = Double
def apply(d: Double): Meters = d
extension (m: Meters)
def +(other: Meters): Meters = m + other
def value: Double = m
object Main:
def main(args: Array[String]): Unit =
val total = Distances(3.0) + Distances(4.0)
println(total.value)منع الالتباس بين الأنواع
الميزة الكبرى هي أن نوعين معتمين مبنيين على النوع الأساسي نفسه غير متوافقين. فلا يمكن الخلط بين Meters وKilometers، رغم أن كليهما من نوع Double.
object Units:
opaque type Meters = Double
opaque type Kilometers = Double
def m(d: Double): Meters = d
def km(d: Double): Kilometers = d
def toMeters(k: Kilometers): Meters = k * 1000
object Main:
def main(args: Array[String]): Unit =
val far = Units.km(2.0)
println(Units.toMeters(far))الأنواع المعتمة مع الحدود
يمكنك منح النوع المعتم حدًا أعلى باستخدام <:. ويكشف ذلك جزءًا من الواجهة العامة مع إبقاء التمثيل الدقيق مخفيًا.
object Ids:
opaque type UserId <: Int = Int
def apply(i: Int): UserId = i
object Main:
def main(args: Array[String]): Unit =
val id = Ids(99)
println(id + 1)الإنشاء الذكي مع التحقق
اجمع بين الأنواع المعتمة ومصنع يتحقق من الصحة لضمان أن تكون القيم صالحة دائمًا. يبقى المُنشئ خاصًا، ولا يكون المصنع الذي يتحقق من الصحة هو المتاح للعامة إلا.
object Ages:
opaque type Age = Int
def of(i: Int): Option[Age] =
if i >= 0 && i < 150 then Some(i) else None
extension (a: Age) def value: Int = a
object Main:
def main(args: Array[String]): Unit =
println(Ages.of(30).map(_.value))
println(Ages.of(-1))تكلفة تشغيلية معدومة
على عكس غلاف فئة القيم أو فئة الحالة، لا يُنشئ النوع المعتم أي كائن أثناء التشغيل. تكون قائمة من Meters حرفيًا قائمة من الأعداد العشرية في JVM، لذلك لا يحدث تغليف.
object Temps:
opaque type Celsius = Double
def c(d: Double): Celsius = d
extension (t: Celsius) def value: Double = t
object Main:
def main(args: Array[String]): Unit =
val readings = List(Temps.c(20.0), Temps.c(21.5))
println(readings.map(_.value).sum)النوع المعتم مقابل الاسم المستعار للنوع
الاسم المستعار العادي من الشكل type X = Y شفاف: يمكن استخدام X وY بالتبادل الكامل في كل مكان. أما النوع المعتم فيخفي هذه المساواة خارج نطاقه، مما يوفر أمانًا حقيقيًا للأنواع.
object Demo:
type Name = String // transparent alias
opaque type Email = String // opaque
def email(s: String): Email = s
extension (e: Email) def raw: String = e
object Main:
def main(args: Array[String]): Unit =
val e = Demo.email("a@b.com")
println(e.raw)النوع المعتم مقابل غلاف فئة الحالة
يوفر غلاف فئة الحالة مثل case class Meters(value: Double) أمانًا للأنواع أيضًا، لكنه يخصص كائنًا في الذاكرة. تمنح الأنواع المعتمة الأمان نفسه مع أداء النوع الأساسي الخام.
object Money:
opaque type Cents = Long
def cents(n: Long): Cents = n
extension (c: Cents)
def +(o: Cents): Cents = c + o
def value: Long = c
object Main:
def main(args: Array[String]): Unit =
val total = Money.cents(150) + Money.cents(50)
println(total.value)متى تستخدم الأنواع المعتمة
استخدم الأنواع المعتمة عندما تريد كتابة قوية للمجال في المسارات الساخنة أو المجموعات الكبيرة.
- ميّز بين الكميات (Meters وSeconds).
- فرض الثوابت التي تم التحقق منها.
- تجنب الكلفة الإضافية لتخصيص أغلفة في الذاكرة.
object Geo:
opaque type Latitude = Double
def lat(d: Double): Option[Latitude] =
if d >= -90 && d <= 90 then Some(d) else None
extension (l: Latitude) def value: Double = l
object Main:
def main(args: Array[String]): Unit =
println(Geo.lat(41.0).map(_.value))اختبار سريع
اختبر مدى فهمك للأنواع المعتمة.
مراجعة
لقد تعلمت الأنواع المعتمة في Scala 3.
opaque type X = Yيخفي المساواة خارج نطاقه.- وفر المصانع وطرائق
extensionلواجهة برمجة التطبيقات. - الأنواع المعتمة المختلفة المبنية على الأساس نفسه غير متوافقة.
- تكشف الحدود العليا الاختيارية باستخدام
<:جزءًا من واجهة برمجة التطبيقات. - لا توجد كلفة أثناء التشغيل، بخلاف أغلفة فئات الحالة.
object Ids:
opaque type OrderId = String
def apply(s: String): OrderId = s
extension (o: OrderId) def raw: String = o
object Main:
def main(args: Array[String]): Unit =
val id = Ids("ORD-1")
println(id.raw)تعلم Scala مع معلم ذكاء اصطناعي — مجانًا
اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.
- الدورات
- 39
- الدروس
- 143
الأسئلة الشائعة
هل درس «الأنواع المعتمة» مجاني؟
نعم — نص درس «الأنواع المعتمة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 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 يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.