0Pricing
Kotlin Academy · درس

@DslMarker: منع تسرّب المستقبلات

استخدم تعليقات @DslMarker التوضيحية لفرض قواعد تداخل DSL وقت الترجمة.

@DslMarker: منع تسرّب المستقبلات درس مجاني في Kotlin Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Kotlin Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Kotlin Academy 4 دروس في المجموع.

مشكلة تسرّب المستقبل

في DSLs المتداخلة، يمكن للامبدا الخاصة ببنّاء داخلي أن تصل عرضًا إلى أعضاء مستقبل خارجي. فعلى سبيل المثال، قد تستدعي داخل كتلة td { } الدالة tr { } من نطاق الجدول الخارجي، وهو أمر غير مقصود في الغالب.

كيف يبدو التسرّب

من دون @DslMarker، يسمح المترجم باستدعاء دوال النطاق الخارجي من أي لامبدا داخلية، مما يؤدي إلى استخدام مربك ومعرّض للأخطاء لـ DSL:

// Without @DslMarker — this compiles but is wrong:
html {
    body {
        table {
            tr {                // outer scope leaks in
                tr {  }         // calling tr inside tr — nonsensical
            }
        }
    }
}

تقديم @DslMarker

‏@DslMarker هو annotation وصفي تطبّقه على فئة annotation الخاصة بك. وستُخفى المستقبلات الضمنية لأي فئة بناء مشروحة بتعليق DSL الخاص بك داخل اللامبدا المتداخلة التي تستخدم تعليق DSL نفسه.

@DslMarker
annotation class HtmlDsl

@HtmlDsl
class Table

@HtmlDsl
class Tr

كيفية عمل إخفاء المستقبل الضمني

عندما تمتلك لامبدا متداخلتان مستقبلًا مشروحًا بتعليق @DslMarker نفسه، يُخفى المستقبل الخارجي داخل اللامبدا الداخلية. ويؤدي الوصول إليه مباشرةً إلى خطأ في وقت الترجمة.

@DslMarker
annotation class HtmlDsl

@HtmlDsl class Html
@HtmlDsl class Body
@HtmlDsl class Div

مثال كامل باستخدام @DslMarker

صرّح بالتعليق، وعلّم فئات البناء، ثم سيكتشف المترجم في وقت الترجمة الاستدعاءات المتداخلة لدوال النطاق الخارجي:

@DslMarker
annotation class MyCfgDsl

@MyCfgDsl
class ServerBuilder {
    var port: Int = 8080
    fun database(block: DbBuilder.() -> Unit) { /*...*/ }
}

@MyCfgDsl
class DbBuilder {
    var url: String = ""
    // Cannot call ServerBuilder.port here — compiler error
}

تجاوز القيد باستخدام this@

إذا احتجت فعلًا إلى الوصول إلى مستقبل خارجي من لامبدا داخلية، فاستخدم مرجعًا موسومًا من الشكل this@OuterClass. فهذا الوصول صريح ومقصود، بخلاف التسرّب العرضي.

fun ServerBuilder.database(block: DbBuilder.() -> Unit) {
    val db = DbBuilder()
    db.block()
    val serverPort = this@ServerBuilder.port  // explicit outer access
}

‏@DslMarker مع DSLs متعددة

ينبغي أن تستخدم DSLs المختلفة تعليقات @DslMarker مختلفة. ولا تتداخل DSLs غير المرتبطة التي تستخدم علامات مختلفة، حتى عند تداخلها.

@DslMarker annotation class HtmlDsl
@DslMarker annotation class GradleDsl
// HtmlDsl and GradleDsl receivers do not hide each other

تطبيقه على فئات البناء والمستقبلات

طبّق تعليق DSL على فئة البناء نفسها. وينتقل التعليق إلى أي معامل لامبدا يكون نوع مستقبله هو تلك الفئة. ولا حاجة إلى إضافة تعليق آخر إلى الدوال الفردية.

دعم بيئة التطوير المتكاملة

تُبرز IntelliJ IDEA وAndroid Studio الوصول إلى المستقبل الخارجي بوصفه خطأً فور استخدام @DslMarker. ويوفر ذلك ملاحظات فورية أثناء إنشاء DSL أو استخدامه.

التصميم من أجل الأمان

يجمع تصميم DSL الجيد بين كل فئة بناء و@DslMarker. وتُعد هذه الزيادة الصغيرة في التعليقات التوضيحية كفيلة بتحسين سهولة استخدام DSL بدرجة كبيرة، ومنع فئات كاملة من الأخطاء لدى مستخدمي DSL.

استخدام المكتبة القياسية

يُستخدم @DslMarker الخاص بـ Kotlin في kotlinx.html وDSL الخاص بالتوجيه في Ktor ونص Kotlin البرمجي في Gradle ومنشئي buildMap/buildList. وهو أداة أساسية في أي مجموعة أدوات DSL جادة.

اختبار سريع

ما الذي يمنعه @DslMarker؟

مراجعة: @DslMarker

أهم النقاط:

  • من دون @DslMarker، تتسرّب المستقبلات الخارجية إلى لامبدا DSL الداخلية
  • عرّف فئة annotation مشروحة بتعليق وصفي، ثم طبّقها على جميع فئات البناء في DSL الخاصة بك
  • لا تستطيع اللامبدا المتداخلة التي تستخدم العلامة نفسها استدعاء أعضاء النطاق الخارجي عرضًا
  • استخدم this@OuterClass عندما تحتاج فعلًا إلى الوصول إلى النطاق الخارجي

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

هل درس «@DslMarker: منع تسرّب المستقبلات» مجاني؟

نعم — نص درس «@DslMarker: منع تسرّب المستقبلات» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Kotlin Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Kotlin Academy 4 دروس في المجموع.

ماذا ستتعلم في «@DslMarker: منع تسرّب المستقبلات»؟

استخدم تعليقات @DslMarker التوضيحية لفرض قواعد تداخل DSL وقت الترجمة. تتمرن على Kotlin Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Kotlin Academy؟

لا تُشترط خبرة سابقة. Kotlin Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «@DslMarker: منع تسرّب المستقبلات»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Kotlin Academy هذا؟

نعم. كل درس في Kotlin Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

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

  1. Lambda مع مستقبل: أساس DSL
  2. @DslMarker: منع تسرّب المستقبلات
  3. إنشاء DSL آمن للأنواع لـ HTML/Config
  4. اختبار DSL وتطويره من دون التأثير في المستخدمين
← العودة إلى Kotlin Academy