يشكّل هذا الدرس التطبيقي التدريبي جزءًا من الدورة التدريبية لبرمجة مطوّري البرامج في 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: إنشاء تسلسل هرمي للأنواع
في هذه الخطوة، تنشئ بعض الصفوف لاستخدامها في الخطوة التالية. تم تناول الدرس الفرعي في درس تطبيقي سابق حول الترميز، ولكن إليك مراجعة موجزة.
- للحفاظ على المثال في تنظيم، أنشئ حزمة جديدة ضمن src وأطلق عليها
generics
. - في حزمة عامات، أنشئ ملف
Aquarium.kt
جديدًا. يتيح لك هذا إعادة تحديد الأمور باستخدام الأسماء نفسها بدون تعارضات، بحيث ينتقل بقية رمزك لهذا الدرس التطبيقي إلى هذا الملف. - إنشاء تسلسل هرمي لأنواع إمدادات المياه ابدأ بجعل
WaterSupply
صفopen
، حتى يمكن تقسيمه فرعيًا. - أضِف معلَمة
var
المنطقية،needsProcessing
. يؤدي هذا إلى إنشاء خاصية قابلة للتغيير تلقائيًا، إلى جانب إرجاع القيمة وأداة التحديد. - أنشِئ فئة فرعية من
TapWater
تساويWaterSupply
، وتمرtrue
باستخدامneedsProcessing
، لأن مياه الصنبور تحتوي على مواد إضافية ضارة بالأسماك. - في
TapWater
، حدِّد دالة اسمهاaddChemicalCleaners()
تضبطneedsProcessing
علىfalse
بعد تنظيف المياه. يمكن ضبط الخاصيةneedsProcessing
منTapWater
لأنهاpublic
تلقائيًا ويمكن للصفوف الفرعية الوصول إليها. آدِي الرَّمْزِ الْكَامِلْ.
package generics
open class WaterSupply(var needsProcessing: Boolean)
class TapWater : WaterSupply(true) {
fun addChemicalCleaners() {
needsProcessing = false
}
}
- أنشئ فئتين فرعيتين إضافيتين لـ
WaterSupply
، وهماFishStoreWater
وLakeWater
. لا يحتاجFishStoreWater
إلى المعالجة، ولكن يجب فلترةLakeWater
باستخدام الطريقةfilter()
. بعد الفلترة، لا تحتاج إلى المعالجة مرة أخرى، لذا عليك ضبطneedsProcessing = false
فيfilter()
.
class FishStoreWater : WaterSupply(false)
class LakeWater : WaterSupply(true) {
fun filter() {
needsProcessing = false
}
}
إذا كنت بحاجة إلى معلومات إضافية، راجِع الدرس السابق حول الاكتساب في Kotlin.
الخطوة 2: إنشاء صف عام
في هذه الخطوة، يمكنك تعديل فئة Aquarium
لدعم أنواع مختلفة من إمدادات المياه.
- في Aquaium.kt، حدِّد فئة
Aquarium
مع<T>
بين قوسَين بعد اسم الفئة. - أضف خاصية غير قابلة للتغيير
waterSupply
من النوعT
إلىAquarium
.
class Aquarium<T>(val waterSupply: T)
- اكتب دالة باسم
genericsExample()
. وهذا ليس جزءًا من فئة، لذلك يمكن أن يرتفع مستوى الملف، مثل دالةmain()
أو تعريفات الفئة. في الدالة، عليك إنشاءAquarium
وتمريرهاWaterSupply
. بما أنّ المعلَمةwaterSupply
عامة، يجب تحديد النوع بين أقواس معقوفة<>
.
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
}
- في
genericsExample()
، يمكن الوصول إلى الرمز المائيwaterSupply
. بما أنّ النوعTapWater
، يمكنك استدعاءaddChemicalCleaners()
بدون أي نوع من أنواع التمثيل.
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
aquarium.waterSupply.addChemicalCleaners()
}
- عند إنشاء الكائن
Aquarium
، يمكنك إزالة الأقواس المعقوفة وما يفصل بينها، لأن لغة Kotlin تستند إلى الاستنتاج. لذلك، لا داعي لقولTapWater
مرتين عند إنشاء المثال. يمكن استنتاج النوع من خلال الوسيطة إلىAquarium
، وستظل قيمة النوعAquarium
من النوعTapWater
.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
aquarium.waterSupply.addChemicalCleaners()
}
- لمعرفة ما يحدث، يُرجى طباعة
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}")
}
- يمكنك إضافة دالة
main()
لطلبgenericsExample()
، ثم تشغيل برنامجك ومراقبة النتيجة.
fun main() {
genericsExample()
}
⇒ water needs processing: true water needs processing: false
الخطوة 3: جعلها أكثر تحديدًا
عامة تعني أنه يمكنك تجاوز أي شيء تقريبًا، وأحيانًا ما يمثل ذلك مشكلة. ستجعل هذه الخطوة الصف Aquarium
أكثر تحديدًا حول ما يمكنك وضعه فيه.
- في
genericsExample()
، أنشِئAquarium
، مع تمرير سلسلة للسمةwaterSupply
، ثم اطبع خاصيةwaterSupply
في حوض السمك.
fun genericsExample() {
val aquarium2 = Aquarium("string")
println(aquarium2.waterSupply)
}
- شغِّل برنامجك لمراقبة النتيجة.
⇒ string
تكون النتيجة هي السلسلة التي مررت بها، لأن Aquarium
لا يضع أي قيود على T.
أي نوع، بما في ذلك String
، يمكن تمريره.
- في
genericsExample()
، أنشِئAquarium
آخر، مع تمريرnull
إلىwaterSupply
. إذا كانت قيمة السمةwaterSupply
فارغة، يمكنك طباعة"waterSupply is null"
.
fun genericsExample() {
val aquarium3 = Aquarium(null)
if (aquarium3.waterSupply == null) {
println("waterSupply is null")
}
}
- يمكنك تشغيل البرنامج وملاحظة النتيجة.
⇒ waterSupply is null
لماذا يمكن اجتياز null
عند إنشاء Aquarium
؟ يعود السبب في ذلك إلى أنه بشكل تلقائي، يشير T
إلى النوع Any?
القابل للإفراغ، وهو النوع الذي يظهر في أعلى التسلسل الهرمي للأنواع. يعادل ما يلي ما كتبته في السابق.
class Aquarium<T: Any?>(val waterSupply: T)
- لمنع السماح باجتياز
null
، اجعلT
من النوعAny
بشكل صريح عن طريق إزالة?
بعدAny
.
class Aquarium<T: Any>(val waterSupply: T)
في هذا السياق، يُطلق على Any
اسم القيود العامة. يعني ذلك أنّه يمكن تمرير أي نوع لـ T
طالما أنه ليس null
.
- وما عليك سوى التأكد من أنه لا يمكن تمرير سوى
WaterSupply
(أو إحدى فئاتها الفرعية) فيT
. استبدِلAny
بـWaterSupply
لتحديد قيد عام أكثر تحديدًا.
class Aquarium<T: WaterSupply>(val waterSupply: T)
الخطوة 4: إضافة المزيد من الحسابات الجارية
في هذه الخطوة، ستتعرّف على دالة check()
لمساعدتك على ضمان عمل الرمز كما هو متوقع. الدالة check()
هي دالة مكتبة عادية في لغة Kotlin. وهو بمثابة تأكيد وسيرمي IllegalStateException
إذا تم تقييم الوسيطة إلى false
.
- أضِف طريقة
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()
استثناءً.
- في
genericsExample()
، أضِف الرمز لإنشاءAquarium
باستخدامLakeWater
، ثم أضِف إليه بعض الماء.
fun genericsExample() {
val aquarium4 = Aquarium(LakeWater())
aquarium4.addWater()
}
- شغِّل برنامجك وستحصل على استثناء لأن المياه تحتاج إلى تصفية أولاً.
⇒ Exception in thread "main" java.lang.IllegalStateException: water supply needs processing first at Aquarium.generics.Aquarium.addWater(Aquarium.kt:21)
- يمكنك إضافة مكالمة لفلترة المياه قبل إضافتها إلى
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's. إنّ شرح النظام الكامل لا يندرج ضمن نطاق هذا البرنامج التدريبي (ومعنيّ تضمين ذلك)، إلّا أنّ المجمِّع سيضع علامة على الأنواع التي لم يتم وضع علامة in
وout
عليها بشكل مناسب، لذا عليك التعرّف عليها.
الخطوة الأولى: تحديد نوع الإيقاف
- في الصف
Aquarium
، غيِّرT: WaterSupply
إلى النوعout
.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
...
}
- في الملف نفسه، خارج الصف، أعلن عن دالة
addItemTo()
تتوقعAquarium
منWaterSupply
.
fun addItemTo(aquarium: Aquarium<WaterSupply>) = println("item added")
- يمكنك الاتصال بالرقم
addItemTo()
منgenericsExample()
وإدارة برنامجك.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
addItemTo(aquarium)
}
⇒ item added
يمكن أن يضمن لغة Kotlin عدم تنفيذ addItemTo()
لأي نوع غير آمن باستخدام WaterSupply
العام، لأنه تم الإعلان عنه على أنه نوع out
.
- إذا أزلت الكلمة الرئيسية
out
، سيظهر للعارض خطأ عند استدعاءaddItemTo()
، لأن لغة Kotlin يمكن't ضمان عدم تنفيذ أي إجراء غير آمن مع النوع.
الخطوة 2: تحديد نوع
النوع in
مشابه للنوع out
، ولكن للأنواع العامة التي يتم تمريرها إلى الدوال فقط، ولا يتم عرضها. وإذا حاولت عرض نوع in
، ستحصل على خطأ في برنامج التجميع. في هذا المثال، ستحدّد نوع in
كجزء من الواجهة.
- في Aquaium.kt، حدّد واجهة
Cleaner
تشتمل علىT
عام ومقيّد بـWaterSupply
. وبما أنها لا تُستخدَم إلا كوسيطة للسمةclean()
، يمكنك جعلها معلَمةin
.
interface Cleaner<in T: WaterSupply> {
fun clean(waterSupply: T)
}
- لاستخدام واجهة
Cleaner
، أنشئ فئةTapWaterCleaner
تنفّذCleaner
لتنظيفTapWater
عن طريق إضافة مواد كيميائية.
class TapWaterCleaner : Cleaner<TapWater> {
override fun clean(waterSupply: TapWater) = waterSupply.addChemicalCleaners()
}
- في الصف
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")
}
}
- عدِّل رمز النموذج
genericsExample()
من أجلTapWaterCleaner
،Aquarium
معTapWater
، ثم أضِف بعض المياه باستخدام المنظّف. وسيستخدم البيانات المنظّمة حسب الحاجة.
fun genericsExample() {
val cleaner = TapWaterCleaner()
val aquarium = Aquarium(TapWater())
aquarium.addWater(cleaner)
}
سيستخدم Kotlin معلومات النوعين in
وout
للتأكد من أن الرمز يستخدم العلامات العامة بشكل آمن. من السهل تذكّر Out
وin
: يمكن تمرير out
من الأنواع كقيم للعرض، ويمكن تمرير أنواع in
من الداخل كوسيطات.
وإذا كنت تريد الاطّلاع على المزيد من المعلومات حول نوع المسائل التي يتم حلّها في الأنواع والأنواع، يمكنك الاطّلاع على المستندات بالتفصيل.
ستتعرّف في هذه المهمة على الدوال العامة وحالات استخدامها. عادةً ما يكون إنشاء دالة عامة فكرة جيدة عندما تستخدم الدالة وسيطة لفئة لها نوع عام.
الخطوة 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
من خلال جعل الدالة عامة.
- لتجعل الدالة عامةً، ضع أقواس معقوفة بعد الكلمة الرئيسية
fun
مع النوع العامT
وأي قيود، في هذه الحالة،WaterSupply
. تغييرAquarium
ليتم حصره علىT
بدلاً منWaterSupply
.
fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) {
println("aquarium water is clean: ${!aquarium.waterSupply.needsProcessing}")
}
T
هي مَعلمة نوع للسمة isWaterClean()
ويتم استخدامها لتحديد النوع العام لأكواريوم. هذا النمط شائع حقًا، وهي فكرة جيدة لقضاء بعض الوقت للعمل على ذلك.
- عليك باستدعاء الدالة
isWaterClean()
من خلال تحديد النوع بين أقواس معقوفة بعد اسم الدالة مباشرةً وقبل الأقواس.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
isWaterClean<TapWater>(aquarium)
}
- بسبب استنتاج النوع من الوسيطة
aquarium
، النوع غير ضروري، لذا عليك إزالته. شغِّل برنامجك ولاحظ النتائج.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
isWaterClean(aquarium)
}
⇒ aquarium water is clean: false
الخطوة 2: إنشاء طريقة عامة باستخدام نوع تم تعديله
يمكنك استخدام الدوال العامة للطرق أيضًا، حتى في الفئات التي تكون من نوعها العام. في هذه الخطوة، يمكنك إضافة طريقة عامة إلى Aquarium
للتحقق مما إذا كان النوع WaterSupply
.
- في فئة
Aquarium
، أعلن عن طريقة، فإنhasWaterSupplyOfType()
التي تستخدم المعلمة العامةR
(سبق أن تم استخدامT
) تقتصر علىWaterSupply
، وتعرضtrue
إذا كانwaterSupply
من النوعR
. هذه هي الوظيفة التي أشرت إليها سابقًا، ولكن في صفAquarium
.
fun <R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R
- يُرجى العلم بأنّ خط
R
النهائي تحته خط باللون الأحمر. ضع المؤشر فوقه لمعرفة ما هو الخطأ. - لإجراء فحص
is
، يجب إخبار لغة Kotlin بأنّ النوع مُحدَّد أو حقيقي ويمكن استخدامه في الدالة. ولإجراء ذلك، ضعinline
أمام الكلمة الرئيسيةfun
وreified
أمام النوع العامR
.
inline fun <reified R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R
بعد إعادة توحيد نوع، يمكنك استخدامه كنوع عادي، لأنه نوع حقيقي بعد التضمين. وهذا يعني أنه يمكنك إجراء is
عمليات تحقق باستخدام النوع.
إذا لم تكن تستخدم reified
هنا، لن يكون النوع &#t9;t"real" كافيًا بلغة Kotlin للسماح بعمليات تحقق is
. وذلك لأن الأنواع غير المُعتمَدة تتوفّر فقط وقت التجميع، ولا يمكن استخدامها في وقت التشغيل بواسطة برنامجك. وستتم مناقشة هذا الأمر أكثر في القسم التالي.
- اجتياز
TapWater
كنوع. مثل استدعاء الدوال العامة، يمكنك استدعاء الطرق العامة باستخدام أقواس معقوفة من النوع الذي يحمل اسم الدالة. يمكنك تشغيل البرنامج وملاحظة النتيجة.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.hasWaterSupplyOfType<TapWater>()) // true
}
⇒ true
الخطوة 3: إنشاء وظائف الإضافة
يمكنك أيضًا استخدام أنواع مُحدَّدة للدوال والدوال العادية.
- خارج الفئة
Aquarium
، حدِّد دالة الإضافة علىWaterSupply
التي تُسمىisOfType()
للتحقّق مما إذا كانت السمةWaterSupply
التي تم تمريرها من نوع معيّن، مثلTapWater
.
inline fun <reified T: WaterSupply> WaterSupply.isOfType() = this is T
- وعليك باستدعاء وظيفة الإضافة بالطريقة نفسها.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.waterSupply.isOfType<TapWater>())
}
⇒ true
باستخدام دوال الإضافات هذه، لا يهم نوع Aquarium
هذا (Aquarium
أو TowerTank
أو بعض الفئات الفرعية الأخرى)، طالما أنها Aquarium
. ويُعدّ استخدام بنية الإسقاط النجمي طريقةً مناسبةً لتحديد مجموعة متنوعة من المطابقات. وعند استخدام إسقاط النجمة، سيضمن Kotlin عدم تنفيذ أي إجراءات غير آمنة أيضًا.
- لاستخدام إسقاط النجمة، ضع
<*>
بعدAquarium
. يجب نقلhasWaterSupplyOfType()
ليكون دالة الإضافة، لأنّه ليس جزءًا من واجهة برمجة التطبيقات الأساسية لخدمةAquarium
.
inline fun <reified R: WaterSupply> Aquarium<*>.hasWaterSupplyOfType() = waterSupply is R
- غيِّر المكالمة إلى
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
وسائل مجدَّدة:
▢ تم احتساب تأثير التنفيذ الفعلي لأحد العناصر.
▢ تم ضبط فهرس إدخال مقيَّد في الصف.
▢ تم تحويل معلمة النوع العامة إلى نوع حقيقي.
▢ تم تفعيل مؤشر خطأ عن بُعد.
انتقل إلى الدرس التالي:
للحصول على نظرة عامة على الدورة التدريبية، بما في ذلك الروابط إلى مختبرات ترميز أخرى، يُرجى الاطّلاع على "Kotlin Botcamp للمبرمجين: مرحبًا بك في الدورة التدريبية&"