هذا الدرس العملي حول الترميز هو جزء من دورة Kotlin التدريبية للمبرمجين. يمكنك تحقيق أقصى استفادة من هذه الدورة التدريبية إذا اتبعت ترتيب الخطوات في دروس البرمجة. استنادًا إلى معرفتك، قد تتمكّن من قراءة بعض الأقسام بسرعة. هذه الدورة التدريبية موجّهة للمبرمجين الذين يعرفون لغة برمجة تعتمد على العناصر ويريدون تعلُّم Kotlin.
مقدمة
في هذا الدرس العملي، ستتعرّف على أساسيات لغة البرمجة Kotlin، مثل أنواع البيانات وعوامل التشغيل والمتغيرات وبُنى التحكّم والمتغيرات التي تقبل القيم الخالية وتلك التي لا تقبلها. هذه الدورة التدريبية موجّهة إلى المبرمجين الذين يعرفون لغة برمجة تعتمد على العناصر ويريدون تعلُّم Kotlin.
بدلاً من إنشاء تطبيق نموذجي واحد، تم تصميم الدروس في هذه الدورة التدريبية لتعزيز معرفتك، ولكنها شبه مستقلة عن بعضها البعض حتى تتمكن من تصفّح الأقسام التي تعرفها. ولربطها ببعضها، تستخدم العديد من الأمثلة سمة حوض السمك. إذا أردت الاطّلاع على قصة حوض السمك بالكامل، يمكنك الرجوع إلى دورة Kotlin Bootcamp للمبرمجين على Udacity.
ما يجب معرفته
- كيفية إنشاء مشروع في IntelliJ IDEA
- كيفية فتح التعليمات البرمجية وتنفيذها في حلقة القراءة والتقييم والطباعة (REPL) في Kotlin في IntelliJ IDEA (أدوات > Kotlin > حلقة القراءة والتقييم والطباعة في Kotlin)
أهداف الدورة التعليمية
- كيفية استخدام أنواع البيانات والعوامل والمتغيرات في Kotlin
- كيفية استخدام القيم المنطقية والشروط
- الفرق بين المتغيرات التي تقبل القيم الخالية والمتغيرات التي لا تقبلها
- طريقة عمل المصفوفات والقوائم والحلقات في Kotlin
الإجراءات التي ستنفذّها
- العمل باستخدام Kotlin REPL للتعرّف على أساسيات Kotlin
في هذه المهمة، ستتعرّف على العوامل والأنواع في لغة البرمجة Kotlin.
الخطوة 1: استكشاف عوامل التشغيل الرقمية
- افتح IntelliJ IDEA إذا لم يكن مفتوحًا.
- لفتح Kotlin REPL، اختَر أدوات (Tools) > Kotlin > Kotlin REPL.
كما هو الحال مع اللغات الأخرى، تستخدم Kotlin الرموز +
و-
و*
و/
للجمع والطرح والضرب والقسمة. تتيح لغة Kotlin أيضًا أنواعًا مختلفة من الأرقام، مثل Int
وLong
وDouble
وFloat
.
- أدخِل العبارات التالية في 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.
- جرِّب بعض الصيغ التي تتضمّن مجموعات مختلفة من الأعداد الصحيحة والأعداد العشرية.
6*50 ⇒ res13: kotlin.Int = 300 6.0*50.0 ⇒ res14: kotlin.Double = 300.0 6.0*50 ⇒ res15: kotlin.Double = 300.0
- استدعِ بعض الطرق على الأرقام. تحتفظ لغة 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
. ويرجع ذلك إلى أنّ تحويل الأرقام الضمني هو مصدر شائع للأخطاء في البرامج. يمكنك دائمًا تعيين قيم من أنواع مختلفة عن طريق التحويل.
- للاطّلاع على بعض عمليات التحويل الممكنة، حدِّد متغيّرًا من النوع
Int
في REPL.
val i: Int = 6
- أنشِئ متغيّرًا جديدًا، ثم أدخِل اسم المتغيّر الموضّح أعلاه، متبوعًا بـ
.to
.
val b1 = i.to
تعرض أداة IntelliJ IDEA قائمة بالاقتراحات المحتملة. تعمل ميزة الإكمال التلقائي هذه مع المتغيرات والعناصر من أي نوع.
- اختَر
toByte()
من القائمة، ثم اطبع المتغيّر.
val b1 = i.toByte()
println(b1)
⇒ 6
- تعيين قيمة
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
- بالنسبة إلى المهام التي عرضت أخطاء، جرِّب عرضها بدلاً من ذلك.
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
- لتسهيل قراءة الثوابت الرقمية الطويلة، تتيح لك لغة 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
، يمكنك تعيين قيمة، ثم تغييرها لاحقًا في البرنامج.
- حدِّد المتغيّرات باستخدام
val
وvar
، ثمّ عيِّن قيمًا جديدة لها.
var fish = 1
fish = 2
val aquarium = 1
aquarium = 2
⇒ error: val cannot be reassigned
يمكنك تعيين قيمة fish
، ثم تعيين قيمة جديدة لها، لأنّها معرَّفة باستخدام var
. محاولة تعيين قيمة جديدة إلى aquarium
تؤدي إلى حدوث خطأ لأنّه تم تعريفه باستخدام val
.
يتم استنتاج النوع الذي تخزّنه في متغيّر عندما يتمكّن المترجم من تحديده من السياق. إذا أردت، يمكنك دائمًا تحديد نوع المتغير بشكل صريح باستخدام صيغة النقطتين.
- حدِّد بعض المتغيّرات وحدِّد النوع بشكلٍ صريح.
var fish: Int = 12
var lakes: Double = 2.5
بعد أن تحدّد أنت أو المترجم نوعًا، لا يمكنك تغييره، وإلا سيظهر لك خطأ.
الخطوة 4: التعرّف على السلاسل
تعمل السلاسل في Kotlin بشكل مشابه تمامًا للسلاسل في أي لغة برمجة أخرى باستخدام "
للسلاسل و'
للأحرف الفردية، ويمكنك ربط السلاسل باستخدام عامل التشغيل +
. يمكنك إنشاء نماذج سلاسل من خلال دمجها مع القيم، ويتم استبدال الاسم $
variable
بالنص الذي يمثّل القيمة. يُطلق على ذلك اسم استيفاء المتغيّرات.
- أنشئ نموذج سلسلة.
val numberOfFish = 5
val numberOfPlants = 12
"I have $numberOfFish fish" + " and $numberOfPlants plants"
⇒ res20: kotlin.String = I have 5 fish and 12 plants
- أنشئ نموذج سلسلة يتضمّن تعبيرًا. كما هو الحال في اللغات الأخرى، يمكن أن تكون القيمة نتيجة تعبير. استخدِم الأقواس المتعرّجة
{}
لتحديد التعبير.
"I have ${numberOfFish + numberOfPlants} fish and plants"
⇒ res21: kotlin.String = I have 17 fish and plants
في هذه المهمة، ستتعرّف على القيم المنطقية والتحقّق من الشروط في لغة البرمجة Kotlin. مثل اللغات الأخرى، تحتوي Kotlin على قيم منطقية وعوامل منطقية مثل أصغر من ويساوي وأكبر من وما إلى ذلك (<
و==
و>
و!=
و<=
و>=
).
- اكتب عبارة
if
/else
.
val numberOfFish = 50
val numberOfPlants = 23
if (numberOfFish > numberOfPlants) {
println("Good ratio!")
} else {
println("Unhealthy ratio")
}
⇒ Good ratio!
- جرِّب استخدام نطاق في عبارة
if
. في Kotlin، يمكن أن يستخدم الشرط الذي تختبره النطاقات أيضًا.
val fish = 50
if (fish in 1..100) {
println(fish)
}
⇒ 50
- اكتب
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!
- جرِّب استخدام عبارة
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
تلقائيًا.
- عرِّف
Int
وأسنِد إليه القيمةnull
.
var rocks: Int = null
⇒ error: null can not be a value of a non-null type Int
- استخدِم عامل علامة الاستفهام،
?
، بعد النوع للإشارة إلى أنّ المتغيّر يمكن أن يكون فارغًا. عرِّفInt?
وأسنِد إليه القيمةnull
.
var marbles: Int? = null
عندما يكون لديك أنواع بيانات معقّدة، مثل قائمة:
- يمكنك السماح بأن تكون عناصر القائمة فارغة.
- يمكنك السماح بأن تكون القائمة فارغة، ولكن إذا لم تكن فارغة، لا يمكن أن تكون عناصرها فارغة.
- يمكنك السماح بأن تكون القائمة أو العناصر فارغة.
سيتم تناول القوائم وبعض أنواع البيانات المعقّدة الأخرى في مهمة لاحقة.
الخطوة 2: التعرّف على علامة الاستفهام العاملان "و" و"؟:"
يمكنك اختبار null
باستخدام عامل التشغيل ?
، ما يوفّر عليك عناء كتابة العديد من عبارات if
/else
.
- اكتب بعض الرموز بالطريقة الأطول للتحقّق مما إذا كان المتغيّر
fishFoodTreats
ليسnull
. بعد ذلك، قلِّل قيمة هذا المتغير.
var fishFoodTreats = 6
if (fishFoodTreats != null) {
fishFoodTreats = fishFoodTreats.dec()
}
- والآن، لنلقِ نظرة على طريقة كتابة ذلك في Kotlin باستخدام عامل التشغيل
?
.
var fishFoodTreats = 6
fishFoodTreats = fishFoodTreats?.dec()
- يمكنك أيضًا ربط اختبارات القيمة الخالية باستخدام عامل التشغيل
?:
. اطّلِع على هذا المثال:
fishFoodTreats = fishFoodTreats?.dec() ?: 0
وهي اختصار لعبارة "إذا كانت قيمة fishFoodTreats
لا تساوي null
، يتم إنقاصها واستخدامها، وإلا يتم استخدام القيمة بعد ?:
، وهي 0". إذا كانت قيمة fishFoodTreats
هي null
، يتم إيقاف التقييم، ولا يتم استدعاء الطريقة dec()
.
ملاحظة حول المؤشرات الفارغة
إذا كنت تحب NullPointerExceptions
، يتيح لك Kotlin الاحتفاظ بها. يحوّل عامل تأكيد عدم القيمة الفارغة، !!
(علامة التعجّب المزدوجة)، أي قيمة إلى نوع غير فارغ ويطرح استثناءً إذا كانت القيمة null
.
val len = s!!.length // throws NullPointerException if s is null
في هذه المهمة، ستتعرّف على المصفوفات والقوائم، بالإضافة إلى طرق مختلفة لإنشاء حلقات في لغة البرمجة Kotlin.
الخطوة 1: إنشاء قوائم
القوائم هي نوع أساسي في Kotlin، وهي تشبه القوائم في اللغات الأخرى.
- عرِّف قائمة باستخدام
listOf
واطبعها. لا يمكن تغيير هذه القائمة.
val school = listOf("mackerel", "trout", "halibut")
println(school)
⇒ [mackerel, trout, halibut]
- تحديد قائمة يمكن تغييرها باستخدام
mutableListOf
إزالة عنصر
val myList = mutableListOf("tuna", "salmon", "shark")
myList.remove("shark")
⇒ res36: kotlin.Boolean = true
تعرض الطريقة remove()
القيمة true
عند إزالة العنصر الذي تم تمريره بنجاح.
الخطوة 2: إنشاء صفائف
مثل اللغات الأخرى، تحتوي Kotlin على مصفوفات. على عكس القوائم في Kotlin التي تتضمّن إصدارات قابلة للتغيير وغير قابلة للتغيير، لا يتوفّر إصدار قابل للتغيير من Array
. بعد إنشاء مصفوفة، يصبح حجمها ثابتًا. لا يمكنك إضافة عناصر أو إزالتها، إلا من خلال النسخ إلى مصفوفة جديدة.
تنطبق القواعد نفسها المتعلّقة باستخدام val
وvar
على المصفوفات كما تنطبق على القوائم.
- عرِّف مصفوفة من السلاسل باستخدام
arrayOf
. استخدِم أداة الصفيفةjava.util.Arrays.toString()
لطباعتها.
val school = arrayOf("shark", "salmon", "minnow")
println(java.util.Arrays.toString(school))
⇒ [shark, salmon, minnow]
- لا يحتوي الصفيف الذي تم تعريفه باستخدام
arrayOf
على نوع مرتبط بالعناصر، لذا يمكنك دمج الأنواع، وهو أمر مفيد. تعريف مصفوفة بأنواع مختلفة
val mix = arrayOf("fish", 2)
- يمكنك أيضًا تعريف المصفوفات بنوع واحد لجميع العناصر. عرِّف مصفوفة من الأعداد الصحيحة باستخدام
intArrayOf()
. تتوفّر أدوات إنشاء أو دوال إنشاء مقابلة لمصفوفات من أنواع أخرى.
val numbers = intArrayOf(1,2,3)
- يمكنك دمج مصفوفتَين باستخدام عامل التشغيل
+
.
val numbers = intArrayOf(1,2,3)
val numbers3 = intArrayOf(4,5,6)
val foo2 = numbers3 + numbers
println(foo2[5])
=> 3
- جرِّب مجموعات مختلفة من المصفوفات والقوائم المتداخلة. كما هو الحال في اللغات الأخرى، يمكنك تضمين المصفوفات والقوائم. أي عندما تضع مصفوفة داخل مصفوفة أخرى، ستحصل على مصفوفة من المصفوفات، وليس مصفوفة مسطّحة تتضمّن محتوى كلتا المصفوفتين. يمكن أن تكون عناصر المصفوفة أيضًا قوائم، ويمكن أن تكون عناصر القوائم مصفوفات.
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 العنوان بدلاً من محتويات المصفوفة.
- من الميزات الرائعة في Kotlin أنّه يمكنك تهيئة المصفوفات باستخدام الرمز بدلاً من تهيئتها إلى 0. جرِّب هذا المثال:
val array = Array (5) { it * 2 }
println(java.util.Arrays.toString(array))
⇒ [0, 2, 4, 6, 8]
يظهر رمز الإعداد بين الأقواس المعقوفة {}
. في الرمز، يشير it
إلى فهرس المصفوفة، بدءًا من 0.
الخطوة 3: إنشاء مقاطع متكرّرة
بعد أن أصبحت لديك قوائم ومصفوفات، يمكنك تكرار العناصر على النحو المتوقّع.
- إنشاء صفيف استخدِم حلقة
for
للتكرار الحلقي خلال المصفوفة وطباعة العناصر.
val school = arrayOf("shark", "salmon", "minnow")
for (element in school) {
print(element + " ")
}
⇒ shark salmon minnow
- في 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. يمكنك الرجوع إلى الخطوة السابقة باستخدام
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
- جرِّب بعض المقاطع المتكرّرة. مثل اللغات الأخرى، تحتوي 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.
- تحويل البيانات الصريح
- تحديد المتغيّرات
- نماذج السلاسل
- القيم القابلة للتصغير
- القوائم
- المصفوفات
-
if
،when
،for
،while
- عامل التشغيل
?:
(Elvis) - عامل التشغيل
!!
برامج تعليمية حول Kotlin
يتضمّن الموقع الإلكتروني https://try.kotlinlang.org برامج تعليمية غنية بصريًا تُعرف باسم Kotlin Koans، ومترجم مستند إلى الويب، ومجموعة كاملة من المستندات المرجعية مع أمثلة.
دورة Udacity التدريبية
للاطّلاع على دورة Udacity التدريبية حول هذا الموضوع، يُرجى الانتقال إلى برنامج Kotlin التدريبي للمبرمجين.
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
على الفور.
انتقِل إلى الدرس التالي:
للحصول على نظرة عامة على الدورة التدريبية، بما في ذلك روابط تؤدي إلى دروس تطبيقية أخرى حول الترميز، يُرجى الاطّلاع على "برنامج Kotlin التدريبي للمبرمجين: مرحبًا بك في الدورة التدريبية".