פונקציות גנריות
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Kotlin של Coddy. שיעור 37 מתוך 57.
פונקציה גנרית עובדת עם כל סוג. פרמטר הטיפוס שלה, שנכתב בתוך סוגריים זוויתיים לפני שם הפונקציה, מייצג את הטיפוס שבו משתמש הקוד שקורא לה. T הוא השם המקובל:
fun <T> firstOr(list: List<T>, default: T): T = if (list.isEmpty()) default else list[0]בתוך main:
println(firstOr(listOf(3, 5), 0) + 1)
println(firstOr(listOf<String>(), "none").uppercase())פלט:
4
NONEKotlin מסיקה את ארגומנט הטיפוס מתוך הארגומנטים. כשאין ממה להסיק אותו, כותבים אותו בעצמכם, כמו ב־listOf<String>() למעלה:
fun <T> repeatItem(item: T, times: Int): List<T> = List(times) { item }בתוך main:
println(repeatItem("ab", 3))
println(repeatItem(7, 2))
val empty = repeatItem<Double>(1.5, 0)
println(empty)פלט:
[ab, ab, ab]
[7, 7]
[]לפונקציה יכולים להיות כמה פרמטרי טיפוס, ופרמטר מטיפוס פונקציה יכול להשתמש בהם. כך פועלות פונקציות ספרייה כמו map עבור כל טיפוס של איבר ותוצאה:
fun <A, B> transform(items: List<A>, f: (A) -> B): List<B> {
val out = mutableListOf<B>()
for (item in items) out.add(f(item))
return out
}
fun <K, V> invert(map: Map<K, V>): Map<V, K> = map.entries.associate { (k, v) -> v to k }בתוך main:
println(transform(listOf("kiwi", "fig")) { it.length })
println(invert(mapOf("a" to 1, "b" to 2)))פלט:
[4, 3]
{1=a, 2=b}פרמטר טיפוס שומר על הטיפוס של הקורא. firstOr(listOf(3, 5), 0) מחזירה Int, ולכן + 1 מתקמפל. גרסה שנכתבה עבור List<Any> הייתה מקבלת גם כל רשימה, אבל הייתה מחזירה Any ומחייבת המרה בכל קריאה:
fun firstAny(list: List<Any>, default: Any): Any = if (list.isEmpty()) default else list[0]
// firstAny(listOf(3, 5), 0) + 1 // שגיאה: ל-Any אין plus
(firstAny(listOf(3, 5), 0) as Int) + 1 // עובר הידור, אבל דורש המרת טיפוס
firstOr(listOf(3, 5), 0) + 1 // גנרי: התוצאה היא Intאתגר
קלכתבו שתי פונקציות גנריות שעובדות עם רשימות מכל סוג. countWhere(items, predicate) מחזירה את מספר האיברים שעומדים בתנאי, פונקציה מסוג (T) -> Boolean. mostCommon(items) מחזירה את האיבר שמופיע בתדירות הגבוהה ביותר (אם יש תיקו, את האיבר שמופיע ראשון ברשימה), או null עבור רשימה ריקה.
הקוד שסופק קורא שורה של מילים ושורה של מספרים, ומדפיס את מספר המילים שאורכן עולה על 3 אותיות, את המילה השכיחה ביותר, את מספר המספרים הזוגיים, את המספר השכיח ביותר, ואת nothing: null עבור רשימה ריקה.
כתבו את הקוד שלכם בקובץ ListTools.kt. הקובץ Main.kt מכיל את קוד הקלט/פלט שסופק, ואי אפשר לערוך אותו.
נסו בעצמכם
fun main() {
// קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
val input = generateSequence(::readLine).toList()
val words = input[0].split(" ")
val numbers = input[1].split(" ").map { it.toInt() }
println("long words: ${countWhere(words) { it.length > 3 }}")
println("most common word: ${mostCommon(words)}")
println("even numbers: ${countWhere(numbers) { it % 2 == 0 }}")
println("most common number: ${mostCommon(numbers)}")
println("nothing: ${mostCommon(listOf<String>())}")
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1מחלקות ואובייקטים
עבודה עם קבציםהגדרת מחלקותבנאים ראשייםבלוקי init ואימות נתוניםבנאים משנייםסיכום – כרטיס ספרייה8טיפוסים גנריים
פונקציות גנריותמחלקות גנריותאילוצי טיפוסיםקווריאנטיות עם in ו-outסיכום – תור עדיפויותתרגלו בעצמכם: Kotlin אונליין