פונקציות הרחבה
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Kotlin של Coddy. שיעור 30 מתוך 57.
פונקציית הרחבה מוסיפה פונקציה לטיפוס קיים בלי לשנות את קוד המקור של הטיפוס. שמה נכתב אחרי טיפוס המקבל, ובתוכה this מתייחס למקבל, ואפשר גם להשמיט אותו:
fun String.shout() = uppercase() + "!"
fun Int.isEven() = this % 2 == 0בתוך main:
println("hello".shout())
println(7.isEven())
println(listOf(1, 2, 3, 4).count { it.isEven() })פלט:
HELLO!
false
2הרחבות פועלות גם על המחלקות שלך, ומאפייני הרחבה מוסיפים מאפיינים מחושבים. הרחבה אינה יכולה להוסיף מצב מאוחסן, והיא יכולה לגשת רק לחברים הציבוריים של המקבל שלה:
class Temperature(val celsius: Double)
val Temperature.fahrenheit: Double
get() = celsius * 9 / 5 + 32
fun Temperature.describe() = "$celsius C is $fahrenheit F"בתוך main:
println(Temperature(100.0).describe())פלט:
100.0 C is 212.0 Fהרחבות נפתרות באופן סטטי: הטיפוס המוצהר של הביטוי קובע איזו הרחבה תיבחר כשהתוכנית מתקמפלת, ולא המחלקה של האובייקט. זהו ההבדל העיקרי בינן לבין איבר שעבר דריסה:
open class Shape {
open fun member() = "shape member"
}
class Circle : Shape() {
override fun member() = "circle member"
}
fun Shape.ext() = "shape extension"
fun Circle.ext() = "circle extension"בתוך main:
val s: Shape = Circle()
println(s.member())
println(s.ext())פלט:
circle member
shape extensionכאשר למחלקה כבר יש איבר בעל אותה חתימה, האיבר תמיד מנצח. השתמש באיברים להתנהגות ששייכת לטיפוס וניתן לדרוס אותה; השתמש בהרחבות לעזרים שמוסיפים מבחוץ, כמו עיצוב עבור מחלקה שאינה בבעלותך:
class Robot {
fun greet() = "member greet"
}
fun Robot.greet() = "extension greet"
fun Robot.wave() = "extension wave"בתוך main:
val r = Robot()
println(r.greet())
println(r.wave())פלט:
member greet
extension waveאתגר
קלMoney(cents) מסופק ב־Money.kt. כתבו עבורו הרחבות ב־MoneyExtensions.kt: את מאפייני ההרחבה Int.dollars ו־Int.cents, שהופכים מספר ל־Money (12.dollars הם 1200 סנט), את Money.format(), שמחזירה $12.50 (או -$3.05 עבור סכומים שליליים), את List<Money>.total(), שמחזירה את הסכום כ־Money, ואת Money.split(parts), שמחלקת לסכומים במספר parts, הנבדלים זה מזה בסנט אחד לכל היותר, כשהגדולים מופיעים ראשונים.
הקוד שסופק קורא שורות כמו 12 dollars או 50 cents ושורה אחרונה עם מספר החלקים. הוא מדפיס כל סכום, total: $12.50 ו־split 3: $4.17 $4.17 $4.16.
הקוד שלכם צריך להיכנס ל־MoneyExtensions.kt ול־Money.kt. הקובץ Main.kt מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.
נסו בעצמכם
fun main() {
// קוד הקלט/פלט שסופק: השאירו אותו כפי שהוא
val input = generateSequence(::readLine).toList()
val amounts = input.dropLast(1).map { line ->
val (n, unit) = line.split(" ")
if (unit == "dollars") n.toInt().dollars else n.toInt().cents
}
for (m in amounts) println(m.format())
val total = amounts.total()
println("total: ${total.format()}")
val parts = input.last().toInt()
println("split $parts: " + total.split(parts).joinToString(" ") { it.format() })
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1מחלקות ואובייקטים
עבודה עם קבציםהגדרת מחלקותבנאים ראשייםבלוקי init ואימות נתוניםבנאים משנייםסיכום – כרטיס ספרייה3אובייקטים ואובייקטים נלווים
הצהרות אובייקטאובייקטים נלוויםקבועים עם constביטויי אובייקטסיכום – משרד הכרטיסים6רב־צורתיות
שליחה דינמיתבדיקות טיפוסים והמרות טיפוסים חכמותwhen עם טיפוסיםפונקציות הרחבהסיכום – שומר גן החיותתרגלו בעצמכם: Kotlin אונליין