برنامج تدريب Kotlin للمبرمجين 2: أساسيات لغة Kotlin

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

مقدمة

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

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

ما يجب معرفته

  • كيفية إنشاء مشروع من خلال IntelliJ IDEA
  • كيفية فتح الرمز وتنفيذه في Kotlin's REPL (Read-Eval-Print Loop) في IntelliJ IDEA (Tools > Kotlin > Kotlin REPL)

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

  • كيفية استخدام أنواع بيانات وعوامل تشغيل ومتغيرات Kotlin
  • كيفية العمل مع المنطقيّة والشروط
  • الفرق بين المتغيّرات الفارغة وغير القابلة للقيم الفارغة
  • آلية عمل المصفوفات والقوائم والحلقات في Kotlin

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

  • يمكنك التعاون مع فريق Kotlin REPL للتعرّف على أساسيات لغة Kotlin.

في هذه المهمة، ستتعرّف على معلومات عن عوامل التشغيل والأنواع في لغة البرمجة Kotlin.

الخطوة 1: استكشاف عوامل التشغيل الرقمية

  1. افتح IntelliJ IDEA، إذا لم يكن مفتوحًا حاليًا.
  2. لفتح Kotlin REPL، اختَر Tools (الأدوات) > Kotlin > Kotlin REPL. (
    )

كما هو الحال مع اللغات الأخرى، يستخدم Kotlin + و- و* و/ علامة الجمع والطرح والأوقات والتقسيم. ويتيح أيضًا لغة Kotlin أنواعًا مختلفة من الأرقام، مثل Int وLong وDouble وFloat.

  1. أدخِل التعبيرات التالية في REPL. للاطّلاع على النتيجة، اضغط على Control+Enter (Command+Enter على جهاز Mac) بعد كل نتيجة.
1+1
⇒ res8: kotlin.Int = 2

53-3
⇒ res9: kotlin.Int = 50

50/10
⇒ res10: kotlin.Int = 5

1.0/2.0
⇒ res11: kotlin.Double = 0.5

2.0*3.5
⇒ res12: kotlin.Double = 7.0

لاحظ أن نتائج العمليات تحتفظ بأنواع المعاملات، لذلك، 1/2 = 0، ولكن 1.0/2.0 = 0.5.

  1. جرّب بعض التعبيرات التي تحتوي على مجموعات مختلفة من الأرقام الصحيحة والأرقام العشرية.
6*50
⇒ res13: kotlin.Int = 300

6.0*50.0
⇒ res14: kotlin.Double = 300.0

6.0*50
⇒ res15: kotlin.Double = 300.0
  1. اتّصِل ببعض الطرق حول الأرقام. يحافظ Kotlin على الأرقام كعناصر أولية، ولكن يسمح لك باستدعاء طرق على الأرقام كما لو كانت عناصر.
2.times(3)
⇒ res5: kotlin.Int = 6

3.5.plus(4)
⇒ res8: kotlin.Double = 7.5

2.4.div(2)
⇒ res9: kotlin.Double = 1.2

الخطوة 2: التدرّب على استخدام الأنواع

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

  1. لعرض بعض النتائج المحتمَلة، اختَر متغيّرًا من النوع Int في REPL.
val i: Int = 6
  1. أنشئ متغيّرًا جديدًا، ثم أدخِل اسم المتغيّر الموضّح أعلاه، متبوعًا بالرقم .to.
val b1 = i.to

يعرض IntelliJ IDEA قائمة بالإكمالات الممكنة. تعمل ميزة الإكمال التلقائي هذه مع المتغيرات والكائنات من أي نوع.

  1. اختَر toByte() من القائمة، ثم اطبع المتغير.
val b1 = i.toByte()
println(b1)
⇒ 6
  1. حدِّد قيمة Byte لمتغيّرات أنواع مختلفة.
val b2: Byte = 1 // OK, literals are checked statically
println(b2)
⇒ 1

val i1: Int = b2
⇒ error: type mismatch: inferred type is Byte but Int was expected

val i2: String = b2
⇒ error: type mismatch: inferred type is Byte but String was expected

val i3: Double = b2
⇒ error: type mismatch: inferred type is Byte but Double was expected
  1. بالنسبة إلى المهام التي عرضت أخطاءً، جرِّب إرسالها بدلاً من ذلك.
val i4: Int = b2.toInt() // OK!
println(i4)
⇒ 1

val i5: String = b2.toString()
println(i5)
⇒ 1

val i6: Double = b2.toDouble()
println(i6)
⇒ 1.0
  1. لتسهيل الثوابت الرقمية الطويلة، تتيح لك لغة Kotlin وضع شرطات سفلية في الأرقام، حيث تكون هذه تناسبك. جرِّب إدخال ثوابت رقمية مختلفة.
val oneMillion = 1_000_000
val socialSecurityNumber = 999_99_9999L
val hexBytes = 0xFF_EC_DE_5E
val bytes = 0b11010010_01101001_10010100_10010010

الخطوة 3: التعرّف على قيمة أنواع المتغيّرات

تدعم لغة Kotlin نوعَين من المتغيّرات: وهما "قابل للتغيير" و"غير قابل للتغيير". باستخدام val، يمكنك تحديد قيمة مرة واحدة. إذا حاولت تخصيص عنصر مرة أخرى، ستظهر لك رسالة خطأ. باستخدام var، يمكنك تخصيص قيمة، ثم تغيير القيمة في وقت لاحق من البرنامج.

  1. حدِّد المتغيرات باستخدام val وvar، ثم خصِّص قيمًا جديدة لها.
var fish = 1
fish = 2
val aquarium = 1
aquarium = 2
⇒ error: val cannot be reassigned

يمكنك تخصيص قيمة fish، ثم تخصيص قيمة جديدة لها، لأنه يتم تحديدها باستخدام var. وتؤدي محاولة تحديد قيمة جديدة إلى aquarium إلى حدوث خطأ نظرًا لأنه تم تحديدها باستخدام val.

يتم استنتاج النوع الذي تخزّنه في المتغيّر عندما تتمكّن أداة التجميع من فهمه من خلال السياق. يمكنك دائمًا تحديد نوع المتغيّر بشكل صريح باستخدام تدوين النقطتين الرأسيتين.

  1. حدِّد بعض المتغيرات وحدِّد النوع بشكل صريح.
var fish: Int = 12
var lakes: Double = 2.5

بعد تعيين النوع من خلالك أو من خلال برنامج التجميع، لا يمكنك تغيير النوع أو ستتلقى رسالة خطأ.

الخطوة 4: التعرّف على السلاسل

تعمل السلاسل في Kotlin إلى حد ما مثل السلاسل في أي لغة برمجة أخرى باستخدام " للسلاسل و' للأحرف الفردية، ويمكنك ربط السلاسل باستخدام عامل التشغيل +. يمكنك إنشاء نماذج سلسلة من خلال دمجها مع القيم، ويتم استبدال اسم $variable بالنص الذي يمثل القيمة. يُسمّى هذا الإجراء الإدخال المتغيّر.

  1. أنشِئ نموذج سلسلة.
val numberOfFish = 5
val numberOfPlants = 12
"I have $numberOfFish fish" + " and $numberOfPlants plants"
⇒ res20: kotlin.String = I have 5 fish and 12 plants
  1. يمكنك إنشاء نموذج سلسلة يتضمن تعبيرًا فيه. وكما هو الحال مع اللغات الأخرى، يمكن أن تكون القيمة ناتجة عن تعبير. استخدِم الأقواس المعقوفة {} لتحديد التعبير.
"I have ${numberOfFish + numberOfPlants} fish and plants"
⇒ res21: kotlin.String = I have 17 fish and plants

في هذه المَهمّة، ستتعلّم معلومات عن القواعد المنطقية والتحقّق من صحة لغة البرمجة Kotlin. وكما هو الحال مع اللغات الأخرى، تشتمل لغة Kotlin على عوامل تشغيل منطقية و منطقية مثل أقل من أو تساوي أو أكبر من ذلك وما إلى ذلك (< و== و> و!= و<= و>=).

  1. اكتب عبارة if/else.
val numberOfFish = 50
val numberOfPlants = 23
if (numberOfFish > numberOfPlants) {
    println("Good ratio!") 
} else {
    println("Unhealthy ratio")
}
⇒ Good ratio!
  1. جرّب نطاقًا في عبارة if. في لغة Kotlin، يمكن للشرط الذي تختبره استخدام النطاقات أيضًا.
val fish = 50
if (fish in 1..100) {
    println(fish)
}
⇒ 50
  1. اكتب if بعدة حالات. بالنسبة إلى الشروط الأكثر تعقيدًا، يمكنك استخدام المنطقي && و المنطقي أو ||. وكما هو الحال مع اللغات الأخرى، يمكنك استخدام عدة حالات باستخدام else if.
if (numberOfFish == 0) {
    println("Empty tank")
} else if (numberOfFish < 40) {
    println("Got fish!")
} else {
    println("That's a lot of fish!")
}
⇒ That's a lot of fish!
  1. جرِّب عبارة when. تتوفّر طريقة أكثر جمالاً لكتابة هذه السلسلة من عبارات if/else if/else باللغة Kotlin، باستخدام عبارة when التي تشبه عبارة switch بلغات أخرى. يمكن للشروط في عبارة when استخدام النطاقات أيضًا.
when (numberOfFish) {
    0  -> println("Empty tank")
    in 1..39 -> println("Got fish!")
    else -> println("That's a lot of fish!")
}
⇒ That's a lot of fish!

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

الخطوة 1: التعرّف على القيمة الفارغة

وفقًا للإعدادات التلقائية، لا يمكن أن تكون المتغيّرات null.

  1. أعلن عن Int وخصص null له.
var rocks: Int = null
⇒ error: null can not be a value of a non-null type Int
  1. استخدِم عامل تشغيل علامة الاستفهام، ?، بعد النوع للإشارة إلى أن المتغيّر يمكن أن يكون فارغًا. أعلن عن Int? وخصص null له.
var marbles: Int? = null

عندما يكون لديك أنواع بيانات معقدة، مثل قائمة:

  • يمكنك السماح بأن تكون عناصر القائمة فارغة.
  • يمكنك السماح بأن تكون القائمة فارغة، ولكن إذا لم تكن القائمة فارغة، لا يمكن أن تكون عناصرها فارغة.
  • يمكنك السماح بجعل كل من القائمة أو العناصر فارغة.

يتم تناول القوائم وبعض أنواع البيانات المعقدة الأخرى في مهمة لاحقة.

الخطوة الثانية: التعرّف على ؟ و?: عاملا التشغيل

يمكنك اختبار null باستخدام عامل التشغيل ?، ما يوفّر عليك عناء كتابة العديد من if/else.

  1. اكتب بعض الرموز بالطريقة الأطول للتحقق مما إذا كان المتغيّر fishFoodTreats ليس null. وبعد ذلك، قلِّل ذلك المتغير.
var fishFoodTreats = 6
if (fishFoodTreats != null) {
    fishFoodTreats = fishFoodTreats.dec()
}
  1. يمكنك الآن البحث عن طريقة Kotlin للكتابة باستخدام عامل التشغيل ?.
var fishFoodTreats = 6
fishFoodTreats = fishFoodTreats?.dec()
  1. ويمكنك أيضًا ربط الاختبارات الفارغة باستخدام عامل التشغيل ?:. انظر إلى هذا المثال:
fishFoodTreats = fishFoodTreats?.dec() ?: 0

إنها مختزَلة مع &القيمة إذا لم تكن القيمة fishFoodTreats null، وتنقص وتستخدمها، وبخلاف ذلك استخدِم القيمة بعد ?:، وهي 0.&quot إذا كانت قيمة fishFoodTreats هي null، يتم إيقاف التقييم ولا يتم استدعاء الطريقة dec().

نقطة عن المؤشرات الفارغة

إذا كنت تحب تطبيق NullPointerExceptions، يسمح لك Kotlin بالاحتفاظ به. تعمل عامل تأكيد العدم خالٍ، !! (double-bang)، على تحويل أي قيمة إلى نوع غير فارغ وعرض استثناء باستثناء القيمة إذا كانت null.

val len = s!!.length   // throws NullPointerException if s is null

في هذه المهمة، يمكنك تعلّم المصفوفات والقوائم، وتعلّم طرقًا مختلفة لإنشاء حلقات بلغة البرمجة Kotlin.

الخطوة 1: إعداد القوائم

القوائم هي نوع أساسي في لغة Kotlin، وهي تشبه القوائم بلغات أخرى.

  1. إعلان قائمة باستخدام listOf وطباعتها. لا يمكن تغيير هذه القائمة.
val school = listOf("mackerel", "trout", "halibut")
println(school)
⇒ [mackerel, trout, halibut]
  1. الإعلان عن قائمة يمكن تغييرها باستخدام mutableListOf. إزالة عنصر
val myList = mutableListOf("tuna", "salmon", "shark")
myList.remove("shark")
⇒ res36: kotlin.Boolean = true

تعرض الطريقة remove() القيمة true عند إزالة العنصر الذي تم تمريره بنجاح.

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

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

تتماثل قواعد استخدام val وvar مع المصفوفات كما هو الحال مع القوائم.

  1. يُرجى تحديد مصفوفة من السلاسل باستخدام arrayOf. استخدم الأداة المساعدة للمصفوفة java.util.Arrays.toString() لطباعتها.
val school = arrayOf("shark", "salmon", "minnow")
println(java.util.Arrays.toString(school))
⇒ [shark, salmon, minnow]
  1. لا يحتوي مصفوفة تم الإعلان عنها مع arrayOf على نوع مرتبط بالعناصر، لذا يمكنك المزج بين الأنواع، وهو أمر مفيد. تحديد مصفوفة من أنواع مختلفة
val mix = arrayOf("fish", 2)
  1. ويمكنك أيضًا تعريف المصفوفات باستخدام نوع واحد لجميع العناصر. ويمكن تعريف مصفوفة من الأعداد الصحيحة باستخدام intArrayOf(). تتوفّر أدوات إنشاء أو وظائف إنشاء مثيلات خاصة بمصفوفات من أنواع أخرى.
val numbers = intArrayOf(1,2,3)
  1. ادمج مصفوفتين مع عامل التشغيل +.
val numbers = intArrayOf(1,2,3)
val numbers3 = intArrayOf(4,5,6)
val foo2 = numbers3 + numbers
println(foo2[5])
=> 3
  1. جرِّب مجموعات مختلفة من المصفوفات والقوائم المدمجة. وكما هو الحال في اللغات الأخرى، يمكنك دمج المصفوفات والقوائم. وهذا يعني أنك عندما تضع مصفوفة داخل مصفوفة، يكون لديك مصفوفة من المصفوفات، وليست مصفوفة مسطحة من محتوى الاثنين. يمكن أيضًا أن تكون عناصر المصفوفة هي قوائم، ويمكن أن تكون عناصر القوائم مصفوفات.
val numbers = intArrayOf(1, 2, 3)
val oceans = listOf("Atlantic", "Pacific")
val oddList = listOf(numbers, oceans, "salmon")
println(oddList)
⇒ [[I@89178b4, [Atlantic, Pacific], salmon]

العنصر الأول numbers هو Array. في حال عدم استخدام أداة مساعدة المصفوفة لطباعتها، يطبع Kotlin العنوان بدلاً من محتوى المصفوفة.

  1. هناك ميزة رائعة في لغة Kotlin وهي أنه يمكنك إعداد المصفوفات باستخدام الرمز بدلاً من إعدادها على 0. جرِّب المثال التالي:
val array = Array (5) { it * 2 }
println(java.util.Arrays.toString(array))
⇒ [0, 2, 4, 6, 8]

يقع رمز الإعداد بين الأقواس المعقوفة، {}. في الرمز، يشير it إلى فهرس المصفوفة الذي يبدأ بـ 0.

الخطوة 3: إنشاء تكرار

الآن بعد أن أصبحت لديك قوائم ومصفوفات، تعمل العناصر بشكل متكرر على النحو المتوقّع.

  1. إنشاء مصفوفة استخدِم حلقة for وتكرار المصفوفة وطباعتها.
val school = arrayOf("shark", "salmon", "minnow")
for (element in school) {
    print(element + " ")
}
⇒ shark salmon minnow
  1. وفي لغة Kotlin، يمكنك التنقل بين العناصر والفهارس في الوقت نفسه. جرِّب المثال التالي:
for ((index, element) in school.withIndex()) {
    println("Item at $index is $element\n")
}
⇒ Item at 0 is shark
Item at 1 is salmon
Item at 2 is minnow
  1. جرِّب أحجام ونطاقات مختلفة للخطوات. يمكنك تحديد نطاقات من الأرقام أو الأحرف، أبجديًا. وكما هو الحال مع اللغات الأخرى، ليس عليك التقدم بمقدار 1. يمكنك الرجوع إلى الصفحة السابقة باستخدام downTo.
for (i in 1..5) print(i)
⇒ 12345

for (i in 5 downTo 1) print(i)
⇒ 54321

for (i in 3..6 step 2) print(i)
⇒ 35

for (i in 'd'..'g') print (i)
⇒ defg
  1. جرّب بعض الحلقات. وكما هو الحال مع اللغات الأخرى، تشتمل لغة Kotlin على while تكرار وdo...while تكرار وعوامل تشغيل ++ و--. لدى Kotlin أيضًا repeat تكرار.
var bubbles = 0
while (bubbles < 50) {
    bubbles++
}
println("$bubbles bubbles in the water\n")

do {
    bubbles--
} while (bubbles > 50)
println("$bubbles bubbles in the water\n")

repeat(2) {
     println("A fish is swimming")
}
⇒ 50 bubbles in the water
49 bubbles in the water
A fish is swimmingA fish is swimming

تشبه لغة Kotlin اللغات الأخرى إلى حد كبير عندما يتعلق الأمر بالأساسيات مثل عوامل التشغيل والقوائم والحلقات، ولكن هناك بعض الاختلافات المهمة.

قد تختلف الميزات التالية بلغة Kotlin عن تلك التي اعتدت عليها في اللغات الأخرى:

  • لا يمكن تحويل أنواع لغة Kotlin بشكل ضمني: استخدم الإرسال.
  • لا يمكن تخصيص المتغيرات المُعلنة عن طريق val إلا مرة واحدة.
  • لا تكون قيم متغيرات Kotlin فارغة تلقائيًا. استخدِم ? لجعل المتغيّرات فارغة.
  • باستخدام Kotlin، يمكنك تكرار التنقل في الفهرس وعناصر المصفوفة في آنٍ واحد في تكرار for.

تشبه بنية لغة Kotlin التالية النصوص البرمجية بلغات أخرى:

  • يمكن أن يكون للمصفوفات والقوائم نوع واحد أو أنواع مختلطة.
  • يمكن دمج المصفوفات والقوائم.
  • يمكنك إنشاء حلقات باستخدام for وwhile وdo/while وrepeat.
  • عبارة when هي إصدار Kotlin' من عبارة switch، ولكن when أكثر مرونة.

مستندات Kotlin

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

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

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

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

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

IntelliJ IDEA

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

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

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

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

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

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

السؤال 1

أي مما يلي يعلن قائمة سلاسل غير قابلة للتغيير؟

val school = arrayOf("shark", "salmon", "minnow")

var school = arrayOf("shark", "salmon", "minnow")

val school = listOf("shark", "salmon", "minnow")

val school = mutableListOf("shark", "salmon", "minnow")

السؤال 2

ما نتيجة الرمز التالي؟
for (i in 3..8 step 2) print(i)

▢ 345678

▢ 468

▢ 38

▢ 357

السؤال 3

ما الغرض من استخدام علامة الاستفهام في هذا الرمز؟
var rocks: Int? = 3

▢ نوع المتغيّر rocks غير ثابت.

▢ يمكن ضبط المتغيّر rocks على قيمة فارغة.

▢ لا يمكن ضبط المتغير rocks على قيمة فارغة.

▢ يجب عدم ضبط المتغير rocks على الفور.

انتقل إلى الدرس التالي: 3- الوظائف

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