Menu
Coddy logo textTech

הגדרת ממשקים

חלק מהיחידה תכנות מונחה עצמים במסלול ה-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() = "[]"
}
challenge icon

אתגר

קל

הצהירו על האיברים של הממשק 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))
    }
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: Kotlin אונליין