Kotlin: برمجة وظيفية أم كائنية التوجه؟ نختار النهج الصحيح

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

Kotlin: عالمين في لغة واحدة

\n\n

هل تساءلت يومًا لماذا يكتب بعض المطورين بلغة Kotlin كما لو كانت Java محسّنة، بينما يحول آخرون الكود إلى سلسلة من تعابير lambda وسلاسل الاستدعاءات؟ الإجابة بسيطة: Kotlin هي لغة متعددة النماذج، تتعامل بشكل ممتاز مع كل من البرمجة كائنية التوجه (OOP) والبرمجة الوظيفية (FP).

\n\n

ولكن كيف لا يضيع المبتدئ في هذا التنوع؟ وكيف لا يقع المطور المتمرس في فخ "كود السباغيتي" بسبب خلط الأنماط؟ في هذا المقال، سنشرح الفروق بين هذين النهجين، وأين وكيف نستخدم كل منهما، وكيف يساعدنا Kotlin في الجمع بين أفضل جوانبهما. استعدوا: سيكون هناك الكثير من الأكواد ولا مجال للملل.

\n\n

إذا كنت تتعلم Kotlin لتطوير تطبيقات Android أو الباك إند، فإن فهم هذه النماذج هو تذكرتك لعالم من الكود النظيف والقابل للقراءة والصيانة. هيا بنا!

\n\n

Kotlin كائني التوجه: الكلاسيكية في غلاف حديث

\n\n

النهج الكائني التوجه يدور حول الكيانات. لديك كلاسات، والكلاسات لها خصائص وطرق. كل ما تفعله البرنامج هو تفاعل بين الكائنات. Kotlin يأخذ أفضل ما في Java، لكنه يضيف السكر: data class، object، الخصائص الكسولة وغيرها الكثير.

\n\n

الكلاسات والوراثة: مثال

\n\n

تخيل أننا نكتب نظامًا لمتجر إلكتروني. النهج الكائني سيبدو هكذا:

\n\n
// كلاس أساسي\nopen class Product(val name: String, val price: Double) {\n    open fun getDescription(): String {\n        return "$name يكلف $price روبل"\n    }\n}\n\n// وراثة\nclass DiscountedProduct(name: String, price: Double, val discount: Double) : Product(name, price) {\n    override fun getDescription(): String {\n        val finalPrice = price * (1 - discount / 100)\n        return "$name بخصم $discount% يكلف ${"%.2f".format(finalPrice)} روبل"\n    }\n}\n\nfun main() {\n    val apple = Product("تفاحة", 50.0)\n    val saleApple = DiscountedProduct("تفاحة", 50.0, 20.0)\n    \n    println(apple.getDescription())  // تفاحة يكلف 50.0 روبل\n    println(saleApple.getDescription()) // تفاحة بخصم 20% يكلف 40.00 روبل\n}
\n\n

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

\n\n

متى يكون OOP هو المسيطر؟

\n
    \n
  • نماذج الأعمال المعقدة — عندما يكون للكيانات حالات وسلوكيات متعددة.
  • \n
  • مكونات واجهة المستخدم — Activity، Fragment، View — كلها OOP كلاسيكي.
  • \n
  • العمل مع قواعد البيانات — ORM (مثل Room) تستخدم الانعكاس والتعليقات التوضيحية المرتبطة بالكلاسات.
  • \n
\n\n

Kotlin الوظيفي: الإيجاز والأمان

\n\n

البرمجة الوظيفية تدور حول الحسابات، وليس الحالات. بدلاً من تغيير الكائنات، نستخدم بيانات غير قابلة للتغيير ودوال نقية. Kotlin لا تجبرك على الكتابة بأسلوب وظيفي، لكنها توفر لك جميع الأدوات لذلك: تعابير lambda، دوال الترتيب الأعلى، تركيبات شبيهة بالـ monad (مثل Result).

\n\n

دوال الترتيب الأعلى: مثال

\n\n

دعنا نحل نفس مشكلة الخصم، ولكن بطريقة وظيفية:

\n\n
data class Product(val name: String, val price: Double)\n\nfun applyDiscount(discount: Double): (Product) -> Product = { product ->\n    val finalPrice = product.price * (1 - discount / 100)\n    product.copy(price = finalPrice)\n}\n\nfun main() {\n    val apple = Product("تفاحة", 50.0)\n    val saleApple = applyDiscount(20.0)(apple)\n    \n    println("${apple.name} يكلف ${apple.price} روبل")           // تفاحة يكلف 50.0 روبل\n    println("${saleApple.name} بخصم يكلف ${saleApple.price} روبل") // تفاحة بخصم يكلف 40.0 روبل\n}
\n\n

لاحظ: لم ننشئ كلاسًا جديدًا. نحن ببساطة نمرر البيانات عبر دالة

المدونات

توصيات الكتب