אובייקטים נלווים
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Kotlin של Coddy. שיעור 13 מתוך 57.
חברים מסוימים שייכים למחלקה כולה ולא למופע יחיד. ב-Kotlin מגדירים אותם בתוך companion object שבמחלקה, וקוראים להם באמצעות שם המחלקה:
class Temperature(val celsius: Double) {
companion object {
fun fromFahrenheit(f: Double) = Temperature((f - 32) * 5 / 9)
}
}בתוך main:
val boiling = Temperature.fromFahrenheit(212.0)
println(boiling.celsius)פלט:
100.0fromFahrenheit היא פונקציית מפעל: פונקציה שיוצרת מופעים. בניגוד לבנאי, יש לה שם תיאורי, והיא יכולה להחזיר null במקום אובייקט. עם private constructor, פונקציית המפעל היא הדרך היחידה ליצור מופע, ולכן היא יכולה לבדוק ולנקות תחילה את הקלט:
class Username private constructor(val text: String) {
companion object {
fun of(raw: String): Username? {
val clean = raw.trim().lowercase()
return if (clean.length in 3..12) Username(clean) else null
}
}
}בתוך main:
println(Username.of(" Ada_L ")?.text)
println(Username.of("x")?.text)
// Username("x") // שגיאה: הבנאי פרטיפלט:
ada_l
nullהאובייקט הנלווה שייך למחלקה, ולכן הוא יכול לקרוא לבנאי הפרטי, והקוד של המחלקה עצמה משתמש באיברי האובייקט הנלווה ללא קידומת. כאן כל כרטיס מקבל את המספר הבא ממונה אחד שכל הכרטיסים חולקים:
class Ticket(val holder: String) {
val number = nextNumber++
companion object {
private var nextNumber = 1
val issued: Int
get() = nextNumber - 1
}
}בתוך main:
val a = Ticket("Ada")
val b = Ticket("Bo")
println("${a.holder} #${a.number}, ${b.holder} #${b.number}")
println("issued: ${Ticket.issued}")פלט:
Ada #1, Bo #2
issued: 2ב-Kotlin אין מילת מפתח static. החברים של האובייקט הנלווה ממלאים את התפקיד הזה: עותק אחד עבור המחלקה כולה, שאליו ניגשים באמצעות ClassName.member. כמו כל אובייקט, האובייקט הנלווה נוצר פעם אחת, כשהמחלקה נמצאת בשימוש לראשונה. שימו בו דברים שאינם תלויים במופע מסוים, כמו פונקציות ליצירת מופעים ומונים משותפים; כל דבר שקורא נתונים של מופע נשאר חבר רגיל.
class User private constructor(val name: String) {
fun greet() = "hi $name" // דורש מופע: user.greet()
companion object {
fun guest() = User("guest") // שייך למחלקה: User.guest()
}
}אתגר
קלהשלימו את המחלקה Coupon. הבנאי שלה פרטי, ולכן יוצרים קופונים באמצעות מפעל Coupon.create(code, percent) באובייקט הנלווה. הוא מחזיר null אלא אם הקוד מורכב מ־4 עד 10 תווים של אותיות גדולות וספרות, והאחוז הוא בין 1 ל־90. האובייקט הנלווה גם סופר את הקופונים שיצר באמצעות created, וקוד חיצוני יכול לקרוא את הערך אך לא לשנות אותו. apply(price) מחזירה את המחיר לאחר ההנחה, בעיגול כלפי מטה (price * (100 - percent) / 100).
הקוד שסופק קורא שורות SAVE10 10 200 (קוד, אחוז, מחיר). הוא מדפיס SAVE10: 180 או invalid coupon SAVE10, ולבסוף created: עם המספר.
הקוד שלכם ייכתב ב־Coupon.kt. הקובץ Main.kt מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.
נסו בעצמכם
fun main() {
// קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
val input = generateSequence(::readLine).toList()
for (line in input) {
val (code, percent, price) = line.split(" ")
val coupon = Coupon.create(code, percent.toInt())
if (coupon == null) println("invalid coupon $code") else println("${coupon.code}: ${coupon.apply(price.toInt())}")
}
println("created: ${Coupon.created}")
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1מחלקות ואובייקטים
עבודה עם קבציםהגדרת מחלקותבנאים ראשייםבלוקי init ואימות נתוניםבנאים משנייםסיכום – כרטיס ספרייה3אובייקטים ואובייקטים נלווים
הצהרות אובייקטאובייקטים נלוויםקבועים עם constביטויי אובייקטסיכום – משרד הכרטיסיםתרגלו בעצמכם: Kotlin אונליין