التحويلات الضمنية
استخدموها بحذر
التحويلات الضمنية درس مجاني في 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 دروس في المجموع.
ما هو التحويل الضمني؟
التحويل الضمني هو تحويل تلقائي لقيمة من نوع إلى آخر عندما يحتاج المترجم إلى ذلك. وقد يجعل واجهات برمجة التطبيقات أسهل استخدامًا، لكن يجب استخدامه بحذر لأنه يخفي ما يحدث.
object Main {
import scala.language.implicitConversions
implicit def intToString(x: Int): String = s"number-$x"
def main(args: Array[String]): Unit = {
val s: String = 42
println(s)
}
}كيفية استخدام المترجم لها
عندما لا يطابق نوع قيمة ما هو متوقع، يبحث المترجم عن تحويل ضمني يعالج عدم التطابق، ويدرجه بصمت.
object Main {
import scala.language.implicitConversions
implicit def doubleToInt(d: Double): Int = d.toInt
def addTen(x: Int): Int = x + 10
def main(args: Array[String]): Unit = {
println(addTen(3.9))
}
}تفعيل الميزة
يتطلب تعريف التحويلات الضمنية استيراد scala.language.implicitConversions، وإلا أصدر المترجم تحذيرًا. وهذا احتكاك مقصود لتثبيط الإفراط في استخدامها.
object Main {
import scala.language.implicitConversions
case class Celsius(value: Double)
implicit def doubleToCelsius(d: Double): Celsius = Celsius(d)
def describe(c: Celsius): String = s"${c.value} C"
def main(args: Array[String]): Unit = {
println(describe(36.6))
}
}التغليف لإضافة أساليب (الأسلوب القديم)
قبل ظهور أساليب التوسعة، كانت التحويلات الضمنية إلى فئة مغلّفة هي الطريقة المتبعة «لإضافة» أساليب إلى الأنواع الموجودة، فيما يُعرف بنمط pimp-my-library.
object Main {
import scala.language.implicitConversions
class RichInt2(x: Int) {
def squared: Int = x * x
}
implicit def toRich(x: Int): RichInt2 = new RichInt2(x)
def main(args: Array[String]): Unit = {
println(5.squared)
}
}الخطر: مفاجآت صامتة
لأن التحويلات غير مرئية في موضع الاستدعاء، فقد تؤدي إلى سلوك مربك وأخطاء يصعب تتبعها. وقد يُجمّع خطأ مطبعي بسبب تشغيل تحويل ضمني عن طريق الخطأ.
object Main {
import scala.language.implicitConversions
implicit def boolToInt(b: Boolean): Int = if (b) 1 else 0
def main(args: Array[String]): Unit = {
val total = true + 4 // surprising! becomes 1 + 4
println(total)
}
}فضّلوا التحويل الصريح
غالبًا ما يكون الخيار الأكثر أمانًا هو استخدام أسلوب عادي ذي اسم بدلًا من التحويل الضمني. قد تكون الشيفرة أطول، لكنها واضحة للقرّاء.
object Main {
case class Celsius(value: Double)
def fromDouble(d: Double): Celsius = Celsius(d)
def main(args: Array[String]): Unit = {
val c = fromDouble(20.5)
println(c)
}
}Scala 3: فئة النوع Conversion
تجعل Scala 3 التحويلات صريحة عبر نسخة given Conversion[A, B]. وهذا يوضح القصد، مع استمرار الحاجة إلى استيراد اللغة.
import scala.language.implicitConversions
object Main:
given Conversion[Int, String] = (x: Int) => s"val-$x"
def main(args: Array[String]): Unit =
val s: String = 7
println(s)لا تُطبّق التحويلات إلا مرة واحدة
يطبّق المترجم تحويلًا ضمنيًا واحدًا كحد أقصى في كل مرة. ولن يربط تحويلين لسد الفجوة، مما يحد من المفاجآت.
object Main {
import scala.language.implicitConversions
implicit def intToStr(x: Int): String = x.toString
def needString(s: String): Int = s.length
def main(args: Array[String]): Unit = {
println(needString(12345))
}
}مواضع العثور على التحويلات
مثل القيم الضمنية الأخرى، تُحلّ التحويلات من النطاق المحلي والاستيرادات والكائنات المرافقة. ويساعد إبقاؤها في استيراد ذي اسم واضح على إظهار وجودها.
object Conversions:
import scala.language.implicitConversions
implicit def strToLen(s: String): Int = s.length
object Main:
import Conversions._
def main(args: Array[String]): Unit =
val n: Int = "hello"
println(n)متى تكون التحويلات مناسبة؟
تشمل الاستخدامات المشروعة التوافق مع أنواع Java، والمساعدات الخاصة بتوسيع الأنواع الرقمية، وحدود المكتبات. وخارج هذه الحالات، فضّلوا أساليب التوسعة أو الدوال الصريحة.
object Main {
import scala.language.implicitConversions
case class Meters(v: Double)
implicit def metersToDouble(m: Meters): Double = m.v
def main(args: Array[String]): Unit = {
val d: Double = Meters(3.5)
println(d * 2)
}
}قاعدة عامة
إذا لم يتمكن القارئ من معرفة حدوث تحويل من الشيفرة، فهذه علامة تحذير. الجؤوا إلى التحويلات الضمنية أخيرًا، بعد أساليب التوسعة والاستدعاءات الصريحة.
object Main {
// Explicit and obvious - usually better
case class Price(cents: Int)
def toDollars(p: Price): Double = p.cents / 100.0
def main(args: Array[String]): Unit = {
println(toDollars(Price(1599)))
}
}تحقّق سريع
ما الخطر الرئيسي للتحويلات الضمنية؟
مراجعة
لقد تعلّمتم التحويلات الضمنية ومحاذيرها:
- تحوّل نوعًا إلى نوع آخر تلقائيًا عند عدم تطابق الأنواع
- تتطلب
import scala.language.implicitConversions - يستخدم Scala 3 الصيغة
given Conversion[A, B] - يُطبَّق تحويل واحد فقط في كل مرة
- استخدموها باعتدال؛ وفضّلوا دوال الامتداد أو الاستدعاءات الصريحة
تعلم 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 يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- المعاملات الضمنية
- given/using في Scala 3
- التحويلات الضمنية
- دوال الامتداد