برنامج تدريب Kotlin للمبرمجين 5.2: مواضيع عامة

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

مقدمة

في هذا الدرس التطبيقي، ستتعرّف على الصفوف العامة والوظائف والأساليب وآلية عملها في لغة Kotlin.

بدلاً من إنشاء نموذج تطبيق واحد، تم تصميم الدروس في هذه الدورة التدريبية لبناء معرفتك، ولكن تكون شبه مستقلة عن بعضها البعض ليتسنى لك تصفح الأقسام التي تعرفها. لربطهما معًا، تستخدم العديد من الأمثلة مظهر معرض أحواض السمك. وإذا أردت الاطّلاع على القصة الكاملة لأحواض السمك، يمكنك الاطّلاع على الدورة التدريبية بعنوان Kotlin Botcamp for Programmers Udacity.

ما يجب معرفته

  • بنية دوال Kotlin وفئاتها وأساليبها
  • كيفية إنشاء صف جديد في IntelliJ IDEA وإدارة برنامج

ما ستتعرَّف عليه

  • كيفية التعامل مع الصفوف والطرق والدوال العامة

الإجراءات التي ستنفذّها

  • إنشاء فئة عامة وإضافة قيود
  • إنشاء نوعَي in وout
  • إنشاء الدوال والأساليب ووظائف الإضافات العامة

مقدّمة حول الأدوية العامة

ولدى لغة البرمجة Kotlin أنواعًا عامة، مثل العديد من لغات البرمجة. يسمح لك النوع العام بجعل الفئة عامة، وبالتالي تجعل الصف أكثر مرونة.

تخيَّل أنك نفذت صفًا واحدًا (MyList) يحتوي على قائمة بالعناصر. بدون إعلانات عامة، ستحتاج إلى تنفيذ إصدار جديد من MyList لكل نوع: إصدار للإصدار Double، واحد للإصدار String، الإصدار للإصدار Fish. باستخدام القوائم العامة، يمكنك جعل القائمة عامة حتى تتمكّن من الاحتفاظ بأي نوع من العناصر. إنه يشبه إنشاء حرف بدل يلائم العديد من الأنواع.

لتحديد نوع عام، يمكنك وضع T بين قوسَين بزاوية <T> بعد اسم الفئة. (يمكنك استخدام حرف آخر أو اسم أطول، ولكن القواعد العامة على النوع العام هي T).

class MyList<T> {
    fun get(pos: Int): T {
        TODO("implement")
    }
    fun addItem(item: T) {}
}

يمكنك الرجوع إلى T كما لو كان نوعًا عاديًا. نوع عرض get() هو T، والمعلمة على addItem() من النوع T. وبالطبع، فإن القوائم العامة مفيدة للغاية، لذلك تم تضمين صف List في لغة Kotlin.

الخطوة 1: إنشاء تسلسل هرمي للأنواع

في هذه الخطوة، تنشئ بعض الصفوف لاستخدامها في الخطوة التالية. تم تناول الدرس الفرعي في درس تطبيقي سابق حول الترميز، ولكن إليك مراجعة موجزة.

  1. للحفاظ على المثال في تنظيم، أنشئ حزمة جديدة ضمن src وأطلق عليها generics.
  2. في حزمة عامات، أنشئ ملف Aquarium.kt جديدًا. يتيح لك هذا إعادة تحديد الأمور باستخدام الأسماء نفسها بدون تعارضات، بحيث ينتقل بقية رمزك لهذا الدرس التطبيقي إلى هذا الملف.
  3. إنشاء تسلسل هرمي لأنواع إمدادات المياه ابدأ بجعل WaterSupply صف open، حتى يمكن تقسيمه فرعيًا.
  4. أضِف معلَمة var المنطقية، needsProcessing. يؤدي هذا إلى إنشاء خاصية قابلة للتغيير تلقائيًا، إلى جانب إرجاع القيمة وأداة التحديد.
  5. أنشِئ فئة فرعية من TapWater تساوي WaterSupply، وتمر true باستخدام needsProcessing، لأن مياه الصنبور تحتوي على مواد إضافية ضارة بالأسماك.
  6. في TapWater، حدِّد دالة اسمها addChemicalCleaners() تضبط needsProcessing على false بعد تنظيف المياه. يمكن ضبط الخاصية needsProcessing من TapWater لأنها public تلقائيًا ويمكن للصفوف الفرعية الوصول إليها. آدِي الرَّمْزِ الْكَامِلْ.
package generics

open class WaterSupply(var needsProcessing: Boolean)

class TapWater : WaterSupply(true) {
   fun addChemicalCleaners() {
       needsProcessing = false
   }
}
  1. أنشئ فئتين فرعيتين إضافيتين لـ WaterSupply، وهما FishStoreWater وLakeWater. لا يحتاج FishStoreWater إلى المعالجة، ولكن يجب فلترة LakeWater باستخدام الطريقة filter(). بعد الفلترة، لا تحتاج إلى المعالجة مرة أخرى، لذا عليك ضبط needsProcessing = false في filter().
class FishStoreWater : WaterSupply(false)

class LakeWater : WaterSupply(true) {
   fun filter() {
       needsProcessing = false
   }
}

إذا كنت بحاجة إلى معلومات إضافية، راجِع الدرس السابق حول الاكتساب في Kotlin.

الخطوة 2: إنشاء صف عام

في هذه الخطوة، يمكنك تعديل فئة Aquarium لدعم أنواع مختلفة من إمدادات المياه.

  1. في Aquaium.kt، حدِّد فئة Aquarium مع <T> بين قوسَين بعد اسم الفئة.
  2. أضف خاصية غير قابلة للتغيير waterSupply من النوع T إلى Aquarium.
class Aquarium<T>(val waterSupply: T)
  1. اكتب دالة باسم genericsExample(). وهذا ليس جزءًا من فئة، لذلك يمكن أن يرتفع مستوى الملف، مثل دالة main() أو تعريفات الفئة. في الدالة، عليك إنشاء Aquarium وتمريرها WaterSupply. بما أنّ المعلَمة waterSupply عامة، يجب تحديد النوع بين أقواس معقوفة <>.
fun genericsExample() {
    val aquarium = Aquarium<TapWater>(TapWater())
}
  1. في genericsExample()، يمكن الوصول إلى الرمز المائي waterSupply. بما أنّ النوع TapWater، يمكنك استدعاء addChemicalCleaners() بدون أي نوع من أنواع التمثيل.
fun genericsExample() {
    val aquarium = Aquarium<TapWater>(TapWater())
    aquarium.waterSupply.addChemicalCleaners()
}
  1. عند إنشاء الكائن Aquarium، يمكنك إزالة الأقواس المعقوفة وما يفصل بينها، لأن لغة Kotlin تستند إلى الاستنتاج. لذلك، لا داعي لقول TapWater مرتين عند إنشاء المثال. يمكن استنتاج النوع من خلال الوسيطة إلى Aquarium، وستظل قيمة النوع Aquarium من النوع TapWater.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    aquarium.waterSupply.addChemicalCleaners()
}
  1. لمعرفة ما يحدث، يُرجى طباعة needsProcessing قبل الاتصال بالرقم addChemicalCleaners() وبعده. فيما يلي الدالة المكتملة.
fun genericsExample() {
    val aquarium = Aquarium<TapWater>(TapWater())
    println("water needs processing: ${aquarium.waterSupply.needsProcessing}")
    aquarium.waterSupply.addChemicalCleaners()
    println("water needs processing: ${aquarium.waterSupply.needsProcessing}")
}
  1. يمكنك إضافة دالة main() لطلب genericsExample()، ثم تشغيل برنامجك ومراقبة النتيجة.
fun main() {
    genericsExample()
}
⇒ water needs processing: true
water needs processing: false

الخطوة 3: جعلها أكثر تحديدًا

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

  1. في genericsExample()، أنشِئ Aquarium، مع تمرير سلسلة للسمة waterSupply، ثم اطبع خاصية waterSupply في حوض السمك.
fun genericsExample() {
    val aquarium2 = Aquarium("string")
    println(aquarium2.waterSupply)
}
  1. شغِّل برنامجك لمراقبة النتيجة.
⇒ string

تكون النتيجة هي السلسلة التي مررت بها، لأن Aquarium لا يضع أي قيود على T.أي نوع، بما في ذلك String، يمكن تمريره.

  1. في genericsExample()، أنشِئ Aquarium آخر، مع تمرير null إلى waterSupply. إذا كانت قيمة السمة waterSupply فارغة، يمكنك طباعة "waterSupply is null".
fun genericsExample() {
    val aquarium3 = Aquarium(null)
    if (aquarium3.waterSupply == null) {
        println("waterSupply is null")
    }
}
  1. يمكنك تشغيل البرنامج وملاحظة النتيجة.
⇒ waterSupply is null

لماذا يمكن اجتياز null عند إنشاء Aquarium؟ يعود السبب في ذلك إلى أنه بشكل تلقائي، يشير T إلى النوع Any? القابل للإفراغ، وهو النوع الذي يظهر في أعلى التسلسل الهرمي للأنواع. يعادل ما يلي ما كتبته في السابق.

class Aquarium<T: Any?>(val waterSupply: T)
  1. لمنع السماح باجتياز null، اجعل T من النوع Any بشكل صريح عن طريق إزالة ? بعد Any.
class Aquarium<T: Any>(val waterSupply: T)

في هذا السياق، يُطلق على Any اسم القيود العامة. يعني ذلك أنّه يمكن تمرير أي نوع لـ T طالما أنه ليس null.

  1. وما عليك سوى التأكد من أنه لا يمكن تمرير سوى WaterSupply (أو إحدى فئاتها الفرعية) في T. استبدِل Any بـ WaterSupply لتحديد قيد عام أكثر تحديدًا.
class Aquarium<T: WaterSupply>(val waterSupply: T)

الخطوة 4: إضافة المزيد من الحسابات الجارية

في هذه الخطوة، ستتعرّف على دالة check() لمساعدتك على ضمان عمل الرمز كما هو متوقع. الدالة check() هي دالة مكتبة عادية في لغة Kotlin. وهو بمثابة تأكيد وسيرمي IllegalStateException إذا تم تقييم الوسيطة إلى false.

  1. أضِف طريقة addWater() إلى صف Aquarium لإضافة المياه، مع check() التي تضمن عدم معالجة المياه أولاً.
class Aquarium<T: WaterSupply>(val waterSupply: T) {
    fun addWater() {
        check(!waterSupply.needsProcessing) { "water supply needs processing first" }
        println("adding water from $waterSupply")
    }    
}

في هذه الحالة، إذا تم ضبط السياسة needsProcessing على "صحيح"، سيلغي check() استثناءً.

  1. في genericsExample()، أضِف الرمز لإنشاء Aquarium باستخدام LakeWater، ثم أضِف إليه بعض الماء.
fun genericsExample() {
    val aquarium4 = Aquarium(LakeWater())
    aquarium4.addWater()
}
  1. شغِّل برنامجك وستحصل على استثناء لأن المياه تحتاج إلى تصفية أولاً.
⇒ Exception in thread "main" java.lang.IllegalStateException: water supply needs processing first
        at Aquarium.generics.Aquarium.addWater(Aquarium.kt:21)
  1. يمكنك إضافة مكالمة لفلترة المياه قبل إضافتها إلى Aquarium. والآن عند تشغيل البرنامج، لا يتم تطبيق أي استثناء.
fun genericsExample() {
    val aquarium4 = Aquarium(LakeWater())
    aquarium4.waterSupply.filter()
    aquarium4.addWater()
}
⇒ adding water from generics.LakeWater@880ec60

يتناول ما سبق أساسيات القواعد العامة. تتناول المهام التالية المزيد، ولكن المفهوم المهم هو كيفية الإعلان عن فئة عامة واستخدامها مع وجود قيود عامة.

في هذه المهمة، ستتعرّف على معلومات عن الأنواع الداخلية والخارجية التي لها خصائص عامة. النوع in هو نوع يمكن تمريره إلى صف فقط، ولا يتم عرضه. النوع out هو نوع لا يمكن عرضه إلا من صف دراسي.

انظر إلى صف Aquarium، وستلاحظ أنه لا يتم عرض النوع العام إلا عند الحصول على الخاصية waterSupply. لا توجد أي طرق تأخذ قيمة من النوع T كمعلمة (باستثناء تعريفها في المُنشئ). يتيح لك لغة Kotlin تحديد أنواع out لهذه الحالة، كما يمكن أن يستنتج معلومات إضافية حول الأماكن التي يمكن استخدام الأنواع فيها بأمان. وبالمثل، يمكنك تحديد أنواع in للأنواع العامة التي يتم تمريرها إلى الأساليب فقط، ولا يتم عرضها. يسمح ذلك لتطبيق Kotlin بإجراء عمليات فحص إضافية لأمان الرمز.

النوعان in وout هما أوامر لنظام نظام Kotlin&#39s. إنّ شرح النظام الكامل لا يندرج ضمن نطاق هذا البرنامج التدريبي (ومعنيّ تضمين ذلك)، إلّا أنّ المجمِّع سيضع علامة على الأنواع التي لم يتم وضع علامة in وout عليها بشكل مناسب، لذا عليك التعرّف عليها.

الخطوة الأولى: تحديد نوع الإيقاف

  1. في الصف Aquarium، غيِّر T: WaterSupply إلى النوع out.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
    ...
}
  1. في الملف نفسه، خارج الصف، أعلن عن دالة addItemTo() تتوقع Aquarium من WaterSupply.
fun addItemTo(aquarium: Aquarium<WaterSupply>) = println("item added")
  1. يمكنك الاتصال بالرقم addItemTo() من genericsExample() وإدارة برنامجك.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    addItemTo(aquarium)
}
⇒ item added

يمكن أن يضمن لغة Kotlin عدم تنفيذ addItemTo() لأي نوع غير آمن باستخدام WaterSupply العام، لأنه تم الإعلان عنه على أنه نوع out.

  1. إذا أزلت الكلمة الرئيسية out، سيظهر للعارض خطأ عند استدعاء addItemTo()، لأن لغة Kotlin يمكن't ضمان عدم تنفيذ أي إجراء غير آمن مع النوع.

الخطوة 2: تحديد نوع

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

  1. في Aquaium.kt، حدّد واجهة Cleaner تشتمل على T عام ومقيّد بـ WaterSupply. وبما أنها لا تُستخدَم إلا كوسيطة للسمة clean()، يمكنك جعلها معلَمة in.
interface Cleaner<in T: WaterSupply> {
    fun clean(waterSupply: T)
}
  1. لاستخدام واجهة Cleaner، أنشئ فئة TapWaterCleaner تنفّذ Cleaner لتنظيف TapWater عن طريق إضافة مواد كيميائية.
class TapWaterCleaner : Cleaner<TapWater> {
    override fun clean(waterSupply: TapWater) =   waterSupply.addChemicalCleaners()
}
  1. في الصف Aquarium، يجب تحديث addWater() للحصول على Cleaner من النوع T، وتنظيف المياه قبل إضافته.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
    fun addWater(cleaner: Cleaner<T>) {
        if (waterSupply.needsProcessing) {
            cleaner.clean(waterSupply)
        }
        println("water added")
    }
}
  1. عدِّل رمز النموذج genericsExample() من أجل TapWaterCleaner، Aquarium مع TapWater، ثم أضِف بعض المياه باستخدام المنظّف. وسيستخدم البيانات المنظّمة حسب الحاجة.
fun genericsExample() {
    val cleaner = TapWaterCleaner()
    val aquarium = Aquarium(TapWater())
    aquarium.addWater(cleaner)
}

سيستخدم Kotlin معلومات النوعين in وout للتأكد من أن الرمز يستخدم العلامات العامة بشكل آمن. من السهل تذكّر Out وin: يمكن تمرير out من الأنواع كقيم للعرض، ويمكن تمرير أنواع in من الداخل كوسيطات.

وإذا كنت تريد الاطّلاع على المزيد من المعلومات حول نوع المسائل التي يتم حلّها في الأنواع والأنواع، يمكنك الاطّلاع على المستندات بالتفصيل.

ستتعرّف في هذه المهمة على الدوال العامة وحالات استخدامها. عادةً ما يكون إنشاء دالة عامة فكرة جيدة عندما تستخدم الدالة وسيطة لفئة لها نوع عام.

الخطوة 1: إنشاء دالة عامة

  1. في generals/Aquaium.kt، عليك إنشاء دالة isWaterClean() تستغرق Aquarium. وعليك تحديد النوع العام للمعلمة، حيث يتمثل أحد الخيارات في استخدام WaterSupply.
fun isWaterClean(aquarium: Aquarium<WaterSupply>) {
   println("aquarium water is clean: ${aquarium.waterSupply.needsProcessing}")
}

ولكن هذا يعني أنّ المعلَمة Aquarium يجب أن تتضمّن معلَمة من النوع out حتى يتم طلب هذه المعلَمة. في بعض الأحيان، يكون out أو in محدودًا جدًا لأنك تحتاج إلى استخدام نوع لكل من الإدخال والإخراج. يمكنك إزالة الشرط out من خلال جعل الدالة عامة.

  1. لتجعل الدالة عامةً، ضع أقواس معقوفة بعد الكلمة الرئيسية fun مع النوع العام T وأي قيود، في هذه الحالة، WaterSupply. تغيير Aquarium ليتم حصره على T بدلاً من WaterSupply.
fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) {
   println("aquarium water is clean: ${!aquarium.waterSupply.needsProcessing}")
}

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

  1. عليك باستدعاء الدالة isWaterClean() من خلال تحديد النوع بين أقواس معقوفة بعد اسم الدالة مباشرةً وقبل الأقواس.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    isWaterClean<TapWater>(aquarium)
}
  1. بسبب استنتاج النوع من الوسيطة aquarium، النوع غير ضروري، لذا عليك إزالته. شغِّل برنامجك ولاحظ النتائج.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    isWaterClean(aquarium)
}
⇒ aquarium water is clean: false

الخطوة 2: إنشاء طريقة عامة باستخدام نوع تم تعديله

يمكنك استخدام الدوال العامة للطرق أيضًا، حتى في الفئات التي تكون من نوعها العام. في هذه الخطوة، يمكنك إضافة طريقة عامة إلى Aquarium للتحقق مما إذا كان النوع WaterSupply.

  1. في فئة Aquarium، أعلن عن طريقة، فإن hasWaterSupplyOfType() التي تستخدم المعلمة العامة R (سبق أن تم استخدام T) تقتصر على WaterSupply، وتعرض true إذا كان waterSupply من النوع R. هذه هي الوظيفة التي أشرت إليها سابقًا، ولكن في صف Aquarium.
fun <R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R
  1. يُرجى العلم بأنّ خط R النهائي تحته خط باللون الأحمر. ضع المؤشر فوقه لمعرفة ما هو الخطأ.
  2. لإجراء فحص is، يجب إخبار لغة Kotlin بأنّ النوع مُحدَّد أو حقيقي ويمكن استخدامه في الدالة. ولإجراء ذلك، ضع inline أمام الكلمة الرئيسية fun وreified أمام النوع العام R.
inline fun <reified R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R

بعد إعادة توحيد نوع، يمكنك استخدامه كنوع عادي، لأنه نوع حقيقي بعد التضمين. وهذا يعني أنه يمكنك إجراء is عمليات تحقق باستخدام النوع.

إذا لم تكن تستخدم reified هنا، لن يكون النوع &#t9;t"real" كافيًا بلغة Kotlin للسماح بعمليات تحقق is. وذلك لأن الأنواع غير المُعتمَدة تتوفّر فقط وقت التجميع، ولا يمكن استخدامها في وقت التشغيل بواسطة برنامجك. وستتم مناقشة هذا الأمر أكثر في القسم التالي.

  1. اجتياز TapWater كنوع. مثل استدعاء الدوال العامة، يمكنك استدعاء الطرق العامة باستخدام أقواس معقوفة من النوع الذي يحمل اسم الدالة. يمكنك تشغيل البرنامج وملاحظة النتيجة.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    println(aquarium.hasWaterSupplyOfType<TapWater>())   // true
}
⇒ true

الخطوة 3: إنشاء وظائف الإضافة

يمكنك أيضًا استخدام أنواع مُحدَّدة للدوال والدوال العادية.

  1. خارج الفئة Aquarium، حدِّد دالة الإضافة على WaterSupply التي تُسمى isOfType() للتحقّق مما إذا كانت السمة WaterSupply التي تم تمريرها من نوع معيّن، مثل TapWater.
inline fun <reified T: WaterSupply> WaterSupply.isOfType() = this is T
  1. وعليك باستدعاء وظيفة الإضافة بالطريقة نفسها.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    println(aquarium.waterSupply.isOfType<TapWater>())  
}
⇒ true

باستخدام دوال الإضافات هذه، لا يهم نوع Aquarium هذا (Aquarium أو TowerTank أو بعض الفئات الفرعية الأخرى)، طالما أنها Aquarium. ويُعدّ استخدام بنية الإسقاط النجمي طريقةً مناسبةً لتحديد مجموعة متنوعة من المطابقات. وعند استخدام إسقاط النجمة، سيضمن Kotlin عدم تنفيذ أي إجراءات غير آمنة أيضًا.

  1. لاستخدام إسقاط النجمة، ضع <*> بعد Aquarium. يجب نقل hasWaterSupplyOfType() ليكون دالة الإضافة، لأنّه ليس جزءًا من واجهة برمجة التطبيقات الأساسية لخدمة Aquarium.
inline fun <reified R: WaterSupply> Aquarium<*>.hasWaterSupplyOfType() = waterSupply is R
  1. غيِّر المكالمة إلى hasWaterSupplyOfType() ونفِّذ برنامجك.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    println(aquarium.hasWaterSupplyOfType<TapWater>())
}
⇒ true

في المثال السابق، كان عليك وضع علامة على النوع العام على أنه reified وإعداد الدالة inline، لأنّ لغة Kotlin بحاجة إلى معرفة ذلك في وقت التشغيل، وليس فقط وقت التجميع.

يتم استخدام جميع الأنواع العامة فقط في وقت التجميع بواسطة Kotlin. ويساعد ذلك المُجمِّع في التأكد من أنك تنفّذ كل شيء بأمان. يتم محو جميع الأنواع العامة حسب وقت التشغيل، وبالتالي تظهر رسالة الخطأ السابقة حول التحقُّق من نوع تم محوه.

وقد اتضح أن بإمكان برنامج التجميع إنشاء رمز صحيح بدون الاحتفاظ بالأنواع العامة حتى وقت التشغيل. لكنه يعني أنك تنفّذ أحيانًا إجراءً ما، مثل أن is يتحقّق من الأنواع العامة التي لا يمكن للمجمِّع دعمها. ولهذا السبب، أضافت لغة Kotlin أنواعًا مُجددة أو حقيقية.

يمكنك الاطّلاع على مزيد من المعلومات حول الأنواع المُحدَّدة ومحو البيانات في مستندات لغة Kotlin.

يركز هذا الدرس على الأسئلة العامة، وهي مهمة لجعل الرمز أكثر مرونة وسهولة في الاستخدام.

  • إنشاء دروس عامة لجعل الترميز أكثر مرونة.
  • يمكنك إضافة قيود عامة للحدّ من الأنواع المستخدمة مع السمات العامة.
  • استخدِم النوعَين in وout مع الإعدادات العامة لتقديم نوع أفضل للتحقُّق من حظر أنواع الانتقال إلى الصفوف أو إرجاعها.
  • أنشئ دوالًا وطرقًا عامة للتعامل مع الأنواع العامة. على سبيل المثال:
    fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) { ... }
  • استخدام وظائف الإضافة العامة لإضافة وظائف غير أساسية إلى صف.
  • في بعض الأحيان، تكون الأنواع المُحدَّدة ضرورية بسبب محو الأنواع. وعلى عكس الأنواع العامة، تستمر الأنواع التي تم تصحيحها في وقت التشغيل.
  • استخدِم الدالة check() للتحقّق من عمل الرمز على النحو المتوقّع. على سبيل المثال:
    check(!waterSupply.needsProcessing) { "water supply needs processing first" }

مستندات Kotlin

إذا كنت بحاجة إلى مزيد من المعلومات عن أي موضوع في هذه الدورة التدريبية، أو إذا واجهتك مشكلة، يمكنك البدء باستخدام https://kotlinlang.org.

برامج تعليمية بلغة Kotlin

يتضمّن الموقع الإلكتروني https://try.kotlinlang.org برامج تعليمية غنية اسمها Kotlin Koans ومترجمًا فوريًا مستندًا إلى الويب ومجموعة كاملة من المستندات المرجعية التي تتضمّن أمثلة.

دورة Udacity التدريبية

للاطّلاع على دورة Udacity التدريبية حول هذا الموضوع، يُرجى الاطّلاع على برنامج Kotlin Campus للمبرمجين.

IntelliJ IDEA

يمكن العثور على مستندات IntelliJ IDEA على الموقع الإلكتروني JetBrains.

يسرد هذا القسم المهام الدراسية المحتملة للطلاب الذين يعملون من خلال هذا الدرس التطبيقي حول الترميز في إطار دورة تدريبية يُديرها معلِّم. يجب أن ينفِّذ المعلّم ما يلي:

  • يمكنك تخصيص واجب منزلي إذا لزم الأمر.
  • التواصل مع الطلاب بشأن كيفية إرسال الواجبات المنزلية
  • وضع درجات للواجبات المنزلية.

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

إذا كنت تستخدم هذا الدرس التطبيقي بنفسك، يمكنك استخدام هذه الواجبات المنزلية لاختبار معلوماتك.

الإجابة عن هذه الأسئلة

السؤال 1

أي مما يلي هو اصطلاح تسمية عامة؟

<Gen>

<Generic>

<T>

<X>

السؤال 2

يُطلق على قيد الأنواع المسموح بها لنوع عام اسم:

▢ قيود عامة

▢ قيود عامة

توضيح ▢

▢ حد أقصى عام للأنواع

السؤال 3

وسائل مجدَّدة:

▢ تم احتساب تأثير التنفيذ الفعلي لأحد العناصر.

▢ تم ضبط فهرس إدخال مقيَّد في الصف.

▢ تم تحويل معلمة النوع العامة إلى نوع حقيقي.

▢ تم تفعيل مؤشر خطأ عن بُعد.

انتقل إلى الدرس التالي: 6- التلاعب الوظيفي

للحصول على نظرة عامة على الدورة التدريبية، بما في ذلك الروابط إلى مختبرات ترميز أخرى، يُرجى الاطّلاع على "Kotlin Botcamp للمبرمجين: مرحبًا بك في الدورة التدريبية&"