הגדרת ממשקים
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Kotlin של Coddy. שיעור 22 מתוך 57.
ממשק מפרט מה טיפוס יכול לעשות בלי להסביר איך. הוא מצהיר על מתודות ועל מאפיינים שכל מחלקה שמממשת אותו חייבת לספק. מחלקה מממשת ממשק באמצעות נקודתיים, כמו במקרה של מחלקת־על, אך ללא סוגריים, מכיוון שלממשק אין בנאי:
interface Drawable {
fun draw(): String
}
class Circle(val radius: Int) : Drawable {
override fun draw() = "circle with radius $radius"
}
class Line(val length: Int) : Drawable {
override fun draw() = "-".repeat(length)
}בתוך main:
println(Circle(3).draw())
println(Line(5).draw())פלט:
circle with radius 3
-----ממשק יכול להצהיר גם על מאפיינים. המחלקה מספקת אותם כמאפייני בנאי, מאפיינים מאוחסנים או getters; הממשק עצמו אינו מאחסן דבר:
interface Vehicle {
val wheels: Int
val label: String
}
class Car(override val label: String) : Vehicle {
override val wheels = 4
}
class Bike : Vehicle {
override val wheels = 2
override val label: String
get() = "bike on $wheels wheels"
}בתוך main:
println("${Car("taxi").label}: ${Car("taxi").wheels}")
println(Bike().label)פלט:
taxi: 4
bike on 2 wheelsיש לממש כל איבר שהממשק מצהיר עליו, עם override לכל אחד מהם, אחרת המחלקה לא תתקמפל. אי אפשר ליצור מופע של ממשק:
interface Speaker {
fun speak(): String
val volume: Int
}
// class Mute : Speaker { override fun speak() = "" } // שגיאה: volume לא מומש
// class Loud : Speaker() { ... } // שגיאה: לממשק אין בנאי
// val s = Speaker() // שגיאה: אי אפשר ליצור מופע של ממשקגם ממשק וגם מחלקה מופשטת מצהירים על איברים ללא גוף. לממשק אין בנאי ואין מצב שמור, ומחלקה יכולה לממש ממשקים רבים אך להרחיב רק מחלקה אחת. השתמשו בממשק עבור יכולת המשותפת למחלקות שאינן קשורות זו לזו, כגון Drawable או Comparable, ובמחלקה מופשטת עבור מחלקת בסיס משותפת עם מצב.
interface Drawable { fun draw(): String } // יכולת
abstract class Shape(val name: String) { abstract fun area(): Double } // מחלקת בסיס עם מצב
class Square(val s: Double) : Shape("square"), Drawable { // מחלקה אחת, מספר בלתי מוגבל של ממשקים
override fun area() = s * s
override fun draw() = "[]"
}אתגר
קלהצהירו על האיברים של הממשק Shape: מאפיין לקריאה בלבד name והמתודות area() ו־perimeter(), ששתיהן מחזירות Double. גרמו ל־Rectangle(width, height) (שם rectangle) ול־Circle(radius) (שם circle, באמצעות Math.PI) לממש אותם. לאחר מכן השלימו את describe(shape), שמחזירה rectangle: area 12.00, perimeter 14.00 עם שתי ספרות אחרי הנקודה העשרונית, תוך שימוש באיברים של Shape בלבד.
הקוד שסופק קורא שורות r,3,4 או c,2, יוצר את הצורה המתאימה ומדפיס describe(shape).
הקוד שלכם ייכתב בקבצים Shape.kt, Rectangle.kt, Circle.kt ו־Functions.kt. הקובץ Main.kt מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.
נסו בעצמכם
fun main() {
// קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
val input = generateSequence(::readLine).toList()
for (line in input) {
val p = line.split(",").map { it.trim() }
val shape: Shape = if (p[0] == "r") Rectangle(p[1].toDouble(), p[2].toDouble()) else Circle(p[1].toDouble())
println(describe(shape))
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1מחלקות ואובייקטים
עבודה עם קבציםהגדרת מחלקותבנאים ראשייםבלוקי init ואימות נתוניםבנאים משנייםסיכום – כרטיס ספרייהתרגלו בעצמכם: Kotlin אונליין