Menu
CoddyTech

מחלקות פתוחות ותת-מחלקות

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Kotlin של Coddy. שיעור 17 מתוך 57.

ירושה מאפשרת למחלקה אחת להתבסס על מחלקה אחרת. מחלקת המשנה מקבלת את כל המאפיינים והמתודות של מחלקת-העל שלה ויכולה להוסיף משלה. מחלקות Kotlin סגורות כברירת מחדל, לכן יש לסמן מחלקה ב-open לפני שמחלקה אחרת יכולה לרשת ממנה:

open class Animal(val name: String) {
    fun describe() = "$name is an animal"
}

class Dog(name: String) : Animal(name) {
    fun fetch() = "$name fetches the ball"
}

בתוך main:

val rex = Dog("Rex")
println(rex.describe())
println(rex.fetch())

פלט:

Rex is an animal
Rex fetches the ball

class Dog(name: String) : Animal(name) מציין ש־Dog יורשת מ־Animal ומעבירה את name לבנאי של מחלקת־העל. לפרמטר אין val, כי המאפיין כבר קיים ב־Animal. אי אפשר לרשת ממחלקה שאינה open:

class Plant(val name: String)
// class Tree(name: String) : Plant(name)   // שגיאה: הטיפוס הזה הוא final, ולכן אי אפשר לרשת ממנו

open class Vehicle(val wheels: Int)
class Bike : Vehicle(2)                     // מעביר ערך קבוע
class Truck(val load: Int) : Vehicle(6)     // מוסיף מאפיין משלו

Dog הוא Animal, ולכן אפשר להשתמש במופע של תת-מחלקה בכל מקום שבו מצופה טיפוס של מחלקת-העל. List<Animal> אחד יכול להכיל כלבים, חתולים ובעלי חיים רגילים, ולכל איבר יש את החברים של Animal:

open class Animal(val name: String) {
    fun describe() = "$name is an animal"
}
class Dog(name: String) : Animal(name)
class Cat(name: String, val indoor: Boolean) : Animal(name)

בתוך main:

val pets: List<Animal> = listOf(Dog("Rex"), Cat("Tom", true), Animal("Generic"))
for (p in pets) println(p.describe())

פלט:

Rex is an animal
Tom is an animal
Generic is an animal

ירושה ממדלת יחס של is-a: כלב הוא בעל חיים, חשבון חיסכון הוא חשבון. כשמחלקה אחת רק משתמשת במחלקה אחרת (למכונית יש מנוע), תן לה מאפיין מהסוג הזה במקום זאת. מחלקות סגורות הן ברירת המחדל ב-Kotlin, ולכן מחלקה שמיועדת להרחבה מצהירה על כך באמצעות open, וכל מחלקה אחרת שומרת על התנהגותה מוגנת מפני מחלקות משנה.

open class Account(val owner: String)
class SavingsAccount(owner: String) : Account(owner)   // הוא סוג של: הורשה

class Engine(val horsepower: Int)
class Car(val engine: Engine)                          // יש לו: מאפיין
challenge icon

אתגר

קל

Manager חוזרת על מה שכבר יש ב-Employee. הפוך את Employee למחלקה פתוחה ואת Manager לתת-המחלקה שלה: Manager(name: String, salary: Int) מעבירה את שני הערכים אל Employee ומשאירה רק את מה שחדש, רשימה פרטית של שמות העובדים שעליהם היא מדווחת, עם addReport(name) ו-teamSize(). ב-Employee,‏ raise(percent) מגדילה את המשכורת באחוז הנתון, בעיגול כלפי מטה, ו-describe() מחזירה את Ada earns 5500.

הקוד שסופק יוצר מנהל מהשורה הראשונה (name,salary), מוסיף כל שם שמופיע אחריה כעובד המדווח אליו, מעניק העלאה של 10% ומדפיס את Ada earns 5500 and leads 2, ואז בודק שמנהל הוא Employee.

הקוד שלך צריך להופיע ב-Employee.kt וב-Manager.kt. הקובץ Main.kt מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.

נסו בעצמכם

fun main() {
    // קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
    val input = generateSequence(::readLine).toList()
    val (name, salary) = input[0].split(",")
    val boss = Manager(name, salary.toInt())
    for (report in input.drop(1)) boss.addReport(report)
    boss.raise(10)
    println("${boss.describe()} and leads ${boss.teamSize()}")
    println("a manager is an employee: ${(boss as Any) is Employee}")
}
quiz iconבחנו את עצמכם

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

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

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