ה-codelab הזה הוא חלק מקורס Kotlin Bootcamp for Programmers. כדי להפיק את המרב מהקורס הזה, מומלץ לעבוד על ה-codelabs לפי הסדר. אם יש לכם ידע בנושא, יכול להיות שתוכלו לדלג על חלק מהקטעים. הקורס הזה מיועד למתכנתים שמכירים שפה מונחית-אובייקטים ורוצים ללמוד Kotlin.
מבוא
ב-codelab הזה תלמדו את היסודות של שפת התכנות Kotlin: סוגי נתונים, אופרטורים, משתנים, מבני בקרה ומשתנים שניתן להקצות להם ערך null לעומת משתנים שלא ניתן להקצות להם ערך null. הקורס הזה מיועד למתכנתים שמכירים שפה מונחית-אובייקטים ורוצים ללמוד Kotlin.
במקום ליצור אפליקציה לדוגמה אחת, השיעורים בקורס הזה נועדו להרחיב את הידע שלכם, אבל הם גם עצמאיים למחצה, כך שתוכלו לדלג על חלקים שאתם מכירים. כדי לקשור בין הדוגמאות, רבות מהן מתבססות על נושא האקווריום. אם אתם רוצים לראות את הסיפור המלא של האקווריום, כדאי לעיין בקורס Kotlin Bootcamp for Programmers ב-Udacity.
מה שכדאי לדעת
- איך יוצרים פרויקט ב-IntelliJ IDEA
- איך פותחים ומריצים קוד ב-REPL (Read-Eval-Print Loop) של Kotlin ב-IntelliJ IDEA (Tools > Kotlin > Kotlin REPL)
מה תלמדו
- איך משתמשים בסוגי נתונים, באופרטורים ובמשתנים של Kotlin
- איך עובדים עם ערכים בוליאניים ותנאים
- ההבדל בין משתנים שניתן להקצות להם ערך null לבין משתנים שלא ניתן להקצות להם ערך null
- הסבר על מערכים, רשימות ולולאות ב-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
- להפעיל כמה methods על מספרים. ב-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 אין המרה מרומזת בין סוגי מספרים, ולכן אי אפשר להקצות ערך short ישירות למשתנה long, או ערך 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
- אם משימות מסוימות החזירו שגיאות, נסו להפעיל Cast במקומן.
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
עם כמה מקרים. לתנאים מורכבים יותר, משתמשים ב-&&
logical and||
וב-&&
logical or||
. כמו בשפות אחרות, אפשר להשתמש ב-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!
במשימה הזו תלמדו על משתנים שיכולים להכיל ערך null לעומת משתנים שלא יכולים להכיל ערך null. שגיאות תכנות שקשורות לערכי null היו המקור לאין ספור באגים. ב-Kotlin מנסים לצמצם את מספר הבאגים על ידי הצגת משתנים שלא יכולים להיות null.
שלב 1: מידע על אפשרות ההגדרה כ-null
כברירת מחדל, אי אפשר null
משתנים.
- מגדירים
Int
ומקצים לוnull
.
var rocks: Int = null
⇒ error: null can not be a value of a non-null type Int
- משתמשים באופרטור סימן השאלה,
?
, אחרי הסוג כדי לציין שמשתנה יכול להיות null. מגדיריםInt?
ומקצים לוnull
.
var marbles: Int? = null
אם יש לכם סוגי נתונים מורכבים, כמו רשימה:
- אפשר לאפשר שהאלמנטים ברשימה יהיו null.
- אפשר לאפשר שהרשימה תהיה null, אבל אם היא לא null, אי אפשר לאפשר שהרכיבים שלה יהיו null.
- אפשר לאפשר שהרשימה או הרכיבים יהיו null.
רשימות וכמה סוגים מורכבים אחרים של נתונים מוסברים במשימה מאוחרת יותר.
שלב 2: מידע על ? האופרטורים and ו-?:
אתם יכולים לבדוק אם יש null
באמצעות האופרטור ?
, וכך לא תצטרכו לכתוב הרבה הצהרות if
/else
.
- כותבים קוד בדרך הארוכה יותר כדי לבדוק אם המשתנה
fishFoodTreats
הוא לאnull
. לאחר מכן מקטינים את המשתנה.
var fishFoodTreats = 6
if (fishFoodTreats != null) {
fishFoodTreats = fishFoodTreats.dec()
}
- עכשיו נראה איך כותבים את זה ב-Kotlin באמצעות האופרטור
?
.
var fishFoodTreats = 6
fishFoodTreats = fishFoodTreats?.dec()
- אפשר גם לשרשר בדיקות null באמצעות האופרטור
?:
. דוגמה:
fishFoodTreats = fishFoodTreats?.dec() ?: 0
זוהי קיצור דרך לביטוי 'אם fishFoodTreats
לא שווה ל-null
, מפחיתים 1 מהערך ומשתמשים בו; אחרת משתמשים בערך אחרי ?:
, שהוא 0'. אם הערך של fishFoodTreats
הוא null
, ההערכה נעצרת והשיטה dec()
לא נקראת.
הערה לגבי מצביעים ריקים
אם אתם ממש אוהבים את NullPointerExceptions
, אתם יכולים להשתמש בהם ב-Kotlin. אופרטור הטענה not-null, !!
(סימן קריאה כפול), ממיר כל ערך לסוג שהוא לא null, וזורק חריגה אם הערך הוא 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
- כדאי לנסות גדלים וטווחים שונים של צעדים. אפשר לציין טווחים של מספרים או של תווים, בסדר אלפביתי. כמו בשפות אחרות, לא חייבים להתקדם בצעד אחד. אפשר להשתמש במקש
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 לא יכולים להיות null. משתמשים ב-
?
כדי להגדיר משתנים כ-nullable. - ב-Kotlin, אפשר להשתמש בלולאת
for
כדי לעבור על האינדקסים והרכיבים של מערך בו-זמנית.
הקונסטרוקציות הבאות בשפת התכנות Kotlin דומות לאלה שבשפות אחרות:
- מערכים ורשימות יכולים להכיל סוג יחיד או סוגים מעורבים.
- אפשר להטמיע מערכים ורשימות בתוך מערכים ורשימות אחרים.
- אפשר ליצור לולאות עם
for
,while
,do
/while
ו-repeat
. - ההצהרה
when
היא הגרסה של Kotlin להצהרהswitch
, אבלwhen
גמישה יותר.
תיעוד של Kotlin
אם אתם רוצים לקבל מידע נוסף על נושא כלשהו בקורס הזה, או אם נתקעתם, https://kotlinlang.org הוא המקום הכי טוב להתחיל בו.
- המרת סוג גלויה
- הגדרת משתנים
- תבניות של מחרוזות
- ערכים שניתן להגדיר כ-Nullable
- רשימות
- מערכים
if
,when
,for
,while
- האופרטור
?:
(Elvis) - אופרטור
!!
מדריכים ל-Kotlin
באתר https://try.kotlinlang.org יש הדרכות מפורטות שנקראות Kotlin Koans, מפרש מבוסס-אינטרנט וסט מלא של מסמכי עזר עם דוגמאות.
קורס של Udacity
כדי לצפות בקורס של Udacity בנושא הזה, אפשר לעבור אל Kotlin Bootcamp for Programmers.
IntelliJ IDEA
מסמכי התיעוד של IntelliJ IDEA זמינים באתר JetBrains.
בקטע הזה מפורטות אפשרויות למשימות ביתיות לתלמידים שעובדים על ה-Codelab הזה כחלק מקורס בהנחיית מדריך. המורה צריך:
- אם צריך, מקצים שיעורי בית.
- להסביר לתלמידים איך להגיש מטלות.
- בודקים את שיעורי הבית.
אנשי ההוראה יכולים להשתמש בהצעות האלה כמה שרוצים, ומומלץ להם להקצות כל שיעורי בית אחרים שהם חושבים שמתאימים.
אם אתם עובדים על ה-codelab הזה לבד, אתם יכולים להשתמש במשימות האלה כדי לבדוק את הידע שלכם.
עונים על השאלות הבאות
שאלה 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
כ-null.
▢ אי אפשר להגדיר את המשתנה rocks
כ-null.
▢ המשתנה rocks
לא צריך להיות מאותחל באופן מיידי.
עוברים לשיעור הבא:
סקירה כללית של הקורס, כולל קישורים ל-Codelabs אחרים, זמינה במאמר "Kotlin Bootcamp for Programmers: Welcome to the course".