Kotlin المزالق وكيفية تجنبها

Kotlin هو كل الغضب في الآونة الأخيرة. وعلى الرغم من أنني أوافق على أن اللغة مدروسة جيدًا ، إلا أنها لها - كما هو الحال مع أي شيء آخر - عيوبها.

في هذه المقالة سأشرح بعض المآثر التي صادفتها وأحاول مساعدتك على تجنبها.

الغموض باطل

في Kotlin ، يمكنك كتابة الكود الخاص بك كما لو أنه لا وجود له على الإطلاق ، وهذا يمكن أن يجعلك تنسى أن null موجود في كل مكان ولكنه يخفي. لنلقِ نظرة على هذه الطبقة البسيطة والبريئة على ما يبدو:

إذا حاولت إنشاء مثيل لهذا ، فستحصل على NullPointerException لأن الشريط حاول الوصول إلى طول c قبل أن تتم تهيئته.

بالطبع كان منطق التطبيق معيبًا هنا ، لكن لا يزال لديك استثناء. أسوأ جزء من هذا هو أن IDE الخاص بك لن يشكو من هذا.

الوجبات السريعة هنا هي أن Kotlin سوف يساعدك في كثير من الحالات (كلها تقريبًا) على تجنب الإبهام ، لكن لا يمكنك نسيانها ومن وقت لآخر ستواجه أشياء مثل هذا.

معالجة القيم الخالية من JDK

مكتبة Kotlin القياسية تتعامل مع القيم الخالية. ولكن إذا كنت تستخدم فئات من JDK ، فسيتعين عليك التعامل مع المؤشرات الخالية المحتملة من وظائف المكتبة باليد.

في معظم الأوقات تكون فصول Kotlin كافية ، لكن في بعض الأحيان يكون عليك استخدام شيء مثل ConcurrentHashMap:

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

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

النظر في المثال التالي:

في هذه الحالة ، يمكنك استخدام نظرة خاطفة والتي في الواقع يمكن أن تعود خالية. لكن المترجم Kotlin لن يشكو حتى تتمكن من الحصول على NullPointerException إذا كانت قائمة الانتظار فارغة.

المشكلة هنا هي أننا استخدمنا قائمة الانتظار وهي واجهة JDK وإذا نظرت إلى تطبيق نظرة خاطفة:

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

الداخلية عليه

عندما تحتوي لامدا على معلمة واحدة ، يمكنك حذفها من الكود الخاص بك واستخدامها بدلاً من ذلك:

"it: اسمًا ضمنيًا لمعلمة واحدة. هناك اصطلاح مفيد آخر هو أنه إذا كانت دالة حرفية تحتوي على معلمة واحدة فقط ، فقد يتم حذف إعلانها (إلى جانب ->) ، وسيكون اسمها". - مستندات Kotlin

المشكلة في هذا عندما تكون لديك وظائف متداخلة كما في هذا المثال:

يستغرق سوى عدد قليل من أن تفقد المسار الذي هو. الحل لهذه المشكلة هو تسمية المعلمات بشكل صريح:

أفضل بكثير!

نسخة غدرا

ألق نظرة على فئة البيانات هذه:

تمنحك فئات البيانات مجموعة من الوظائف ويمكنك أيضًا عمل نسخة منها. خمن ما سوف يطبع هذا:

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

يكمن حل هذه المشكلة في الانتباه إلى فئات البيانات الخاصة بك ، وإذا كانت يجب أن تكون كائنات قيمة ، فاجعلها واحدة:

هناك مشكلة أخرى في فئات البيانات: لا يمكنك إخبار Kotlin عن الحقول التي تريد وضعها في يساوي / hashCode ، يمكنك فقط تجاوز كليهما وكتابتهما باليد. ضعه بمخيلتك.

تسرب داخلي

الق نظرة على هذا المثال:

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

ملحقات عالمية غير عامة

فائدة وظائف التمديد عالية بلا شك ، ولكن مع قوة كبيرة تأتي مسؤولية كبيرة. يمكنك - على سبيل المثال - كتابة وظائف الامتداد إلى فئات JDK والتي ستكون مرئية للمشروع بأكمله. قد يكون ذلك مشكلة عندما تكون غير عامة وتمثل عمليات لا معنى لها إلا في سياق محلي:

الآن كل شخص في مشروعك سوف يخدش رؤوسهم عندما يصطدم بهذا. لذلك أعتقد أنه من الجيد أن تفكر مرتين قبل أن تكتب وظائف الامتداد ولكن يمكن أن تكون قوية حقًا. فيما يلي بعض الأمثلة التي قد تكون مفيدة:

وحدة العائدين lambdas مقابل تحويل Java Java

عندما يكون لديك وظائف تقبل lambdas ، يمكنك حذف الكلمة الرئيسية المرتجعة إذا كان نوع الإرجاع lambda هو Unit:

هذا جيد ، ولكن إذا اتصلت بهذا من Java ، فستواجه مشكلة محرجة تتمثل في الحاجة إلى إرجاع الوحدة:

هذا clunky جدا من جانب جافا. إذا حاولت تنفيذ هذا العمل من Java ، فيمكنك تحديد واجهة:

ثم يمكنك استخدام تحويل SAM الخاص بـ Java لجعل هذا الأمر بسيطًا جدًا:

ولكن بعد ذلك من جانب Kotlin ، تصبح الفوضى

المشكلة هي أن Kotlin لا يدعم تحويل SAM لفئات Kotlin وأنه يعمل فقط مع فئات Java. اقتراحي هو أنه في الحالات البسيطة ، استخدم واجهات SAM المدمجة في Java مثل المستهلك:

جافا تتداخل مع مجموعات لا يمكن تعديلها

تمنحك Kotlin أشكالًا غير قابلة للتغيير لفئات مجموعة JDK:

هذه إضافة لطيفة للغاية ولكن إذا نظرت إلى هذا من جانب Java ، فسترى واجهة برمجة تطبيقات JDK في Set:

إذا حاولت تعديل هذه المجموعة ، فسيحدث نفس الشيء كما لو كنت قد استخدمت طريقة Java's Collections.unmodifiableSet (). لا أعرف ما إذا كان يمكن (أو ينبغي) حل هذا الأمر ، لكن هذا شيء يمكنك تذكره عند العمل مع إصدارات Kotlin الثابتة لمجموعات Java.

لا تفرط في واجهات

هذه ليست سوى مشكلة من منظور التشغيل المتداخل ، ولكن Kotlin لا يدعم التعليق التوضيحيJvmOverloads في interaceand ولا يمكنك استخدامه في التخطيات إما:

في الوقت الحالي ، الشيء الوحيد الذي يمكنك القيام به لزيادة التحميل هو تعريفها باليد:

ضعها في الاعتبار على الرغم من أنه يمكنك اقتراح تحسينات على Kotlin نفسها باستخدام KEEP (Kotlin Evolution and Enhancement Process). KEEP يشبه JEP في Java ، لكن بالطبع KEEP لديه شريط أحمر أقل بكثير من JEP.

استنتاج

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

وبشكل عام ، أعتقد أن المشكلات المذكورة أعلاه يمكن حلها بسهولة أو لا تكون حرجة وأنها لا تحد من قابلية استخدام اللغة نفسها.

شكرا للقراءة! يمكنك قراءة المزيد من مقالاتي على مدونتي.