Kotlin: run, let, apply, also, with — متى نستخدم ماذا؟ تحليل كامل مع أمثلة
مرحبًا يا صديقي! إذا كنت تدرس Kotlin وتريد كتابة كود نظيف وموجز، فستواجه عاجلاً أم آجلاً خمس دوال سحرية: run، let، apply، also و with. هذه هي دوال النطاق (scope functions) — فهي تسمح بتنفيذ الكود في سياق كائن وتُبسّط الحياة بشكل كبير.
ولكن هناك مشكلة: العديد من المبتدئين (وليس فقط) يخلطون بين متى يستخدمون أيًا منها. هذا السؤال هو واحد من أكثر الأسئلة شيوعًا على Stack Overflow، واليوم سنفهم مرة وإلى الأبد كيف لا نخطئ. لن نقوم فقط بسرد القواعد — بل سنعرض أمثلة حقيقية من الممارسة يمكنك استخدامها فورًا في مشاريعك.
ما هي دوال النطاق وما فائدتها؟
دوال النطاق هي دوال تنشئ نطاق رؤية مؤقت لكائن. داخل هذا النطاق، يمكنك الوصول إلى الكائن عبر it أو this. الفرق الرئيسي بينها هو كيفية إرجاع النتيجة و كيفية الإشارة إلى السياق.
إليك ورقة غش سريعة سنملؤها بالأمثلة:
let— السياق:it، يُرجع: نتيجة اللامدا. يُستخدم للتحقق من القيم غير الفارغة وسلاسل الاستدعاءات.run— السياق:this، يُرجع: نتيجة اللامدا. دالة متعددة الاستخدامات، غالبًا للتهيئة والحسابات.apply— السياق:this، يُرجع: الكائن نفسه. مثالي لضبط خصائص الكائن.also— السياق:it، يُرجع: الكائن نفسه. جيد للإجراءات الإضافية (تسجيل، تحقق).with— ليست دالة امتداد، السياق:this، تُرجع: نتيجة اللامدا. مفيدة لتجميع استدعاءات كائن واحد دون إنشاء كائن جديد.
تذكر القاعدة الأساسية: اختيار الدالة يعتمد على ما تحتاجه — إرجاع الكائن أم النتيجة، وكيف تريد الإشارة إلى السياق (عبر it أو this).
1. let — ملك السلاسل الآمنة
let هو أفضل صديق لك عندما تحتاج للعمل مع كائنات nullable. ينفذ الكود فقط إذا كان الكائن لا يساوي null. يتم تمرير السياق كـ it.
مثال: تحويل آمن
val name: String? = "أندريه"// بدون let:if (name != null) { println("طول الاسم: ${name.length}")}
// مع let (أكثر أناقة بكثير):name?.let { println("طول الاسم: ${it.length}")}let مناسب أيضًا لسلاسل العمليات. على سبيل المثال، عندما تحتاج لتحويل كائن إلى آخر:
val numbers = listOf(1, 2, null, 4, null, 6)val nonNullSquared = numbers .mapNotNull { it } .let { list -> list.map { it * it } }println(nonNullSquared) // [1, 4, 16, 36]متى نستخدم let:
- التحقق من null (الحالة الأكثر شيوعًا).
- تحويل قيمة إلى أخرى.
- تنفيذ سلسلة عمليات على النتيجة.
2. apply — المُنشئ بلا كلمات زائدة
apply يُرجع الكائن نفسه، وداخل اللامدا السياق هو this. هذه أداة مثالية لضبط الكائن قبل الاستخدام. انسَ الكتل الطويلة من set!
مثال: ضبط View (Android) أو data class
data class User(var name: String = "", var age: Int = 0)
val user = User().apply { name = "ماريا" age = 25}println(user) // User(name=ماريا, age=25)
// والأفضل — ضبط TextView:val textView = TextView(context).apply { text = "مرحبًا، Kotlin!" textSize = 18f setTextCo