دوال النطاق — ما هي، أنواعها واستخداماتها في Kotlin

المؤلف: IT Sectr نُشر: 2026-06-23 وقت القراءة: 8 دق

دوال النطاق في Kotlin هي خمس دوال من المكتبة القياسية (let, run, with, apply, also) تنفذ كتلة من التعليمات البرمجية في سياق كائن. تختلف في طريقة الوصول إلى الكائن (من خلال it أو this) والقيمة المعادة (كائن السياق أو نتيجة lambda). وفقًا لوثائق Kotlin (2026)، فإن الاختيار الصحيح لدالة النطاق يقلل الكود التكراري بنسبة 25–40%. دوال النطاق تساعد في كتابة تهيئة الكائنات وتكوينها وتحويلاتها بأسلوب تعريفي.

النقاط الرئيسية

  • دوال النطاق — خمس دوال في Kotlin (let, run, with, apply, also) للعمل في سياق كائن
  • السياق من خلال this — run, with, apply تستخدم this، مما يسمح باستدعاء دوال الكائن مباشرة
  • السياق من خلال it — let و also تمرران الكائن كمعامل it بتسمية صريحة
  • إرجاع الكائن — apply و also تعيدان كائن السياق لسلاسل الاستدعاءات
  • إرجاع النتيجة — let, run و with تعيدان آخر تعبير في lambda

ما هي دوال النطاق؟

دوال النطاق هي مجموعة من خمس دوال (let, run, with, apply, also) مدمجة في المكتبة القياسية لـ Kotlin. كل منها تأخذ lambda وتغير النطاق مؤقتًا بحيث يتم تنفيذ الكود داخل lambda في سياق كائن معين. هذا يلغي تكرار اسم الكائن عند الاستدعاءات المتعددة ويجمع العمليات المرتبطة في كتلة واحدة.

خاصيتان رئيسيتان تميزان دوال النطاق: طريقة الوصول إلى كائن السياق (من خلال this أو من خلال it) والقيمة المعادة (كائن السياق نفسه أو نتيجة lambda). الوصول من خلال this يجعل الكائن مستقبلًا ضمنيًا — يتم استدعاء الدوال والخصائص بدون بادئة. الوصول من خلال it يمرر الكائن كمعامل صريح لـ lambda. إرجاع الكائن يسمح ببناء السلاسل، وإرجاع النتيجة يسمح بتعيين القيمة المحولة.

تاريخيًا، ظهرت دوال النطاق كبديل للنمط الكلاسيكي Builder والمتغيرات المؤقتة للتهيئة. بدلاً من إنشاء فئة builder منفصلة، يكتب المطور apply { خاصية1 = ...; خاصية2 = ... }. هذا يقلل حجم الكود ويجعل التهيئة أكثر قابلية للقراءة. في نظام Kotlin البيئي، تُستخدم دوال النطاق في جميع الأطر والمكتبات كأسلوب لغوي قياسي.

مقارنة دوال النطاق: this مقابل it، إرجاع الكائن مقابل النتيجة

يتم تحديد اختيار دالة النطاق الصحيحة من خلال سؤالين: هل تريد استخدام this أو it للوصول إلى الكائن، وهل تريد إرجاع الكائن نفسه أم نتيجة lambda. مزيج الخاصيتين الثنائيتين يعطي أربعة خيارات ممكنة، و with تحتل مكانة خاصة كالدالة الوحيدة التي ليست امتدادًا.

الدالةالوصولالإرجاعامتداد؟السيناريو النموذجي
letitنتيجة lambdaنعمتحويل، تحقق من null
runthisنتيجة lambdaنعمحساب مع سياق
withthisنتيجة lambdaلاتجميع الاستدعاءات
applythisكائن السياقنعمتهيئة الخصائص
alsoitكائن السياقنعمتأثيرات جانبية، تسجيل

لتكوين كائن دون إرجاع قيمة جديدة، استخدم apply (الوصول من خلال this) أو also (الوصول من خلال it). لحساب قيمة جديدة بناءً على كائن، استخدم let (الوصول من خلال it) أو run (الوصول من خلال this). لتجميع الاستدعاءات دون سلسلة، استخدم with. اتباع هذا المخطط يجعل الكود قابلاً للتنبؤ للمطورين الآخرين الملمين بـ Kotlin.

apply و also: التكوين مع إرجاع الكائن

apply هي دالة نطاق تعيد كائن السياق وتوفر الوصول إليه من خلال this. إنها الأداة المثالية لتهيئة خصائص الكائن بعد إنشائه. داخل كتلة apply يمكن تعيين الخصائص دون تكرار اسم الكائن. تعيد الدالة الكائن نفسه، مما يسمح بإدراج apply في سلاسل أو استخدامه في المهيآت.

kotlin
data class ServerConfig(
    var host: String = "localhost",
    var port: Int = 8080,
    var useTls: Boolean = false
)

val config = ServerConfig().apply {
    host = "api.example.com"
    port = 443
    useTls = true
}

في المثال apply يقوم بتكوين ServerConfig بالوصول إلى الخصائص مباشرة من خلال this (this محذوف). بدون apply كان سيتعين كتابة config.host = ..., config.port = ... — ثلاث مراجع متكررة لنفس المتغير. إرجاع الكائن يسمح بحفظ نتيجة التكوين في val config. also، على عكس apply، تمرر الكائن من خلال it وهي مناسبة للإجراءات الجانبية.

kotlin
fun saveUser(user: User) {
    validate(user).also { result ->
        println("نتيجة التحقق: $result")
    }
    val savedUser = user.also {
        log("Saving user ${it.id}")
        database.save(it)
    }
}

في المثال also يُستخدم للتسجيل — أثناء إرجاع الكائن الأصلي، يقوم بإجراء جانبي (إظهار رسالة) دون تعديل الكائن. هذه سلسلة: validate(user) تعيد User، also تسجل النتيجة وتمرر المستخدم للأمام. also مفيدة أيضًا لإضافة عناصر إلى المجموعات أو التصحيح في منتصف سلسلة التحويلات.

let و run: التحويلات والحسابات

let هي دالة نطاق تعيد نتيجة lambda وتمرر السياق من خلال it. إنها الدالة الرئيسية للتحويلات الآمنة مع null: إذا كان الكائن nullable، فإن التركيبة ?.let { } تنفذ الكتلة فقط للقيم غير الفارغة. تُستخدم let أيضًا لتحديد نطاق المتغيرات المؤقتة وللتحويلات الشبيهة بـ map من نوع إلى آخر.

kotlin
fun findUser(id: Int): User?

val displayName = findUser(42)?.let { user ->
    "${user.name} (${user.email})"
} ?: "Unknown user"

// let مع تحويل المجموعة
val numbers = listOf("1", "2", "3")
val parsed = numbers.firstOrNull()?.let {
    it.toIntOrNull()
} ?: 0

في المثال الأول let يُستدعى من خلال ?. — يتم تنفيذ الكتلة فقط إذا أعادت findUser قيمة غير فارغة. تأخذ lambda المستخدم من خلال it (يمكن إعادة تسميته للوضوح) وتعيد سلسلة منسقة. إذا لم يتم العثور على المستخدم، عامل Elvis ?: يعطي قيمة افتراضية. في المثال الثاني let يحول سلسلة نصية إلى رقم مع احتمال null.

run هو نظير let مع الوصول من خلال this، ويعيد نتيجة lambda. run مناسب للحسابات التي تتطلب سياق الكائن ولكنها تعيد قيمة جديدة. استدعاء run() بدون كائن (مثل run { ... }) ينشئ نطاقًا مؤقتًا للمتغيرات. with هي غير امتداد مع الوصول من خلال this، مناسبة لتجميع الاستدعاءات دون سلسلة.

kotlin
// run كحساب يعتمد على السياق
val transformed = listOf(1, 2, 3).run {
    filter { it > 1 }.map { it * 10 }
}
println(transformed) // [20, 30]

// with لتجميع الاستدعاءات
val info = with(StringBuilder()) {
    append("Name: ")
    append("Alice")
    toString()
}

في المثال run على قائمة يعيد نتيجة التصفية والتحويل — التحويل نفسه، وليس القائمة. with تأخذ StringBuilder كوسيطة (ليس من خلال نقطة) وتعمل داخليًا مع this: append, append, toString. نتيجة with هي السلسلة info. الاختيار بين run و with غالبًا ما يكون ذاتيًا، لكن with مفضلة عندما يتم تمرير الكائن من مكان آخر دون سلسلة.

with: سياق بدون امتداد

with تختلف عن دوال النطاق الأخرى في أنها ليست دالة امتداد. تأخذ الكائن كوسيطة أولى و lambda كوسيطة ثانية. داخل lambda يكون الكائن متاحًا من خلال this. with مناسبة لتجميع استدعاءات دوال الكائن دون حفظ النتيجة أو عندما تحتاج إلى “الدخول” مؤقتًا إلى سياق لقراءة عدة خصائص.

kotlin
val user = User("Alice", "alice@example.com", "Admin")

val summary = with(user) {
    "User $name has role $role and email $email"
}
println(summary)

// with لتهيئة مكونات واجهة المستخدم
with(TextView(context)) {
    text = "Hello"
    textSize = 18.0f
    setTextColor(Color.BLUE)
}

في المثال الأول with يشكل السلسلة summary بالوصول إلى خصائص user مباشرة من خلال this. بدون with كان سيتعين كتابة "User ${user.name} has role ${user.role}" — تكرار user. في المثال الثاني with تجمع تكوين TextView: جميع الدوال والخصائص تُستدعى على كائن واحد دون تكرار. عيب with — عدم القدرة على استخدامها في سلسلة، لأنها ليست امتدادًا ولا تعيد كائن السياق.

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

أي دالة نطاق تختار لتهيئة كائن؟

استخدم apply — تعيد الكائن وتوفر الوصول من خلال this، مما يسمح بتعيين الخصائص دون تكرار اسم الكائن. also مناسبة إذا كنت بحاجة إلى معامل it صريح للتمييز عن خصائص الكائن.

ما الفرق بين let و run؟

let تمرر السياق من خلال it (معامل صريح)، run — من خلال this (مستقبل ضمني). let مناسبة لفحوصات null والتحويلات، run — للحسابات مع السياق. كلتاهما تعيدان نتيجة lambda.

متى نستخدم with بدلاً من apply؟

with ليست امتدادًا — تأخذ الكائن كوسيطة. استخدم with لتجميع الاستدعاءات عندما لا تكون هناك حاجة لسلسلة. apply هي امتداد يعيد الكائن، مناسب في المهيآت وأنماط builder.

هل يمكن تداخل دالة نطاق داخل أخرى؟

نعم، لكن كن حذرًا مع this — this المتداخل يسبب ارتباكًا. استخدم let أو also بأسماء صريحة للسياقات المتداخلة لتجنب الغموض عند الإشارة إلى الكائن الخارجي.

ما هي دالة النطاق الأكثر أداءً؟

جميع دوال النطاق هي inline، لذلك لا تنشئ عبئًا من الفئات المجهولة. الفرق في الأداء بينها ضئيل. يجب أن يعتمد الاختيار على قابلية القراءة والاتفاقيات، وليس على السرعة.

الخلاصة

  • دوال النطاق — خمس دوال inline في Kotlin (let, run, with, apply, also) لتنفيذ كود في سياق كائن
  • apply تعيد كائن السياق مع الوصول من خلال this — مثالية لتهيئة الخصائص
  • also تعيد كائن السياق مع الوصول من خلال it — مناسبة للتسجيل والإجراءات الجانبية
  • let تعيد نتيجة lambda مع الوصول من خلال it — أساس التحويلات الآمنة مع null
  • run تعيد نتيجة lambda مع الوصول من خلال this — مناسبة للحسابات مع السياق
  • with ليست امتدادًا وتعير نتيجة lambda — مناسبة لتجميع الاستدعاءات دون سلسلة
  • مزيج الخصائص (this/it وإرجاع الكائن/النتيجة) يحدد اختيار دالة النطاق لكل مهمة

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا