כיתה Kotlin – בנאי Kotlin

במדריך זה, נדבר על מושגי תכנות מונה של Kotlin. נדבר בפרט על Class ב-Kotlin. נסתכל גם על בנאי Kotlin, מגבלי גישה ו-Class אבסטרקטית.

Class ב-Kotlin

קבוצת פונקציות ומאפיינים מוגדרים בתוך תבנית כחולה. ב-Kotlin, Class מוגדרת באמצעות מילת המפתח class ואחריה שם ה-Class. הגוף הולך בתוך סוגריים מסולסלים.

class FirstClass {
}

המופע של ה-Class משולש באופן הבא:

val firstClass =  FirstClass()
var new = FirstClass() //here new is the name of the var.

בניגוד ל-Java, new אינה מילת מפתח ב-Kotlin. Class ב-Kotlin ברירת מחדל הם final. לכן, המקביל של ההגדרות לעיל ב-Java ייראה כמו כן:

public final class FirstClass {
}

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

open class Me{
}

האנוטציה open מאפשרת לאחרים לירש מ-Class זו.

דוגמה על Class ב-Kotlin

בואו ניצור מחלקה עם מספר פונקציות ומאפיין. נראה איך לגשת לפונקציות ולמאפיינים של המחלקה הזו. בנוסף, נראה איך להגדיר מאפייני חבר.

class User {

    var loggedIn: Boolean = false
    val cantChangeValue = "Hi"
    
    fun logOn() {
        loggedIn = true
    }
    
    fun logOff() {
        loggedIn = false
    }
}

fun main(args: Array<String>) {

    val user = User()
    println(user.loggedIn) //false
    user.logOn()
    println(user.loggedIn) //true
    user.logOff()
    println(user.loggedIn) //false
    user.cantChangeValue = "Hey" //won't compile. Can't modify a final variable.

}

הפונקציה main שייכת למחלקה Test.kt. כדי לגשת לחברים ולפונקציות, עלינו להשתמש באופרטור הנקודה. מאפיין val לא יכול להיות מוגדר שוב באמצעות אופרטור הנקודה.

Kotlin init

לבלוק האתחול של Kotlin מוגדר כפי שמוצג למטה.

class User {
    
    init{
        print("Class instance is initialised.")
    }

    var loggedIn: Boolean = false
    val cantChangeValue = "Hi"

    fun logOn() {
        loggedIn = true
    }

    fun logOff() {
        loggedIn = false
    }
}

הקוד בתוך הבלוק init הוא הראשון שיתבצע כאשר המחלקה מתווצרת. בלוק init יופעל בכל פעם שהמחלקה מתווצרת, עם כל סוג של בנאי כמו שנראה אחר כך. ניתן לכתוב מספר בלוקי אתחול במחלקה. הם יופעלו בסדר כפי שמוצג למטה.

class MultiInit(name: String) {

    init {
        println("First initializer block that prints ${name}")
    }

    init {
        println("Second initializer block that prints ${name.length}")
    }
}

fun main(args: Array) {
    var multiInit = MultiInit("Kotlin")
}

//הודפס בלוג בקונסול.
//בלוק אתחול ראשון שמדפיס Kotlin
//בלוק אתחול שני שמדפיס 6

מחלקות Kotlin מאפשרות להדפיס מאפיינים בהגדרה עצמה על ידי שימוש בפונקציה also כפי שמוצג למטה.

class MultiInit(name: String) {
    val firstProperty = "First property: $name".also(::println)

    init {
        println("First initializer block that prints ${name}")
    }

    val secondProperty = "Second property: ${name.length}".also(::println)

    init {
        println("Second initializer block that prints ${name.length}")
    }
}

fun main(args: Array) {

    var multiInit = MultiInit("Kotlin")
}

//הודפס.
//מאפיין ראשון: Kotlin
//בלוק אתחול ראשון שמדפיס Kotlin
//מאפיין שני: 6
//בלוק אתחול שני שמדפיס 6

בנאי Kotlin

בנאים ב-Kotlin הם פונקציות חבר מיוחדות המשמשות לאתחול תכונות. בנאים ב-Kotlin נכתבים ומאורגנים בצורה שונה מ-Java. כברירת מחדל, לכל מחלקה יש בנאי ריק כפי שמוצג למטה:

class Student {
    var name: String
    val age : Int

    init {
        name = "Anupam"
        age = 24
    }

    init {
        name = "Anupam Chugh"
        //age = 26
    }
}

fun main(args: Array) {
    
    val student = Student()
    println("${student.name} age is ${student.age}")
    student.name = "Your"
    //student.age = 26 //לא יתרגם. age הוא val
    println("${student.name} age is ${student.age}")

}

//הדפסה בקונסול:
//Anupam Chugh גילו הוא 24
//גילך הוא 24

בנאים ראשיים

בנאים ראשיים ב-Kotlin מוגדרים ישירות בכותרת המחלקה כפי שמוצג למטה.

class User(var name: String, var isAdmin: Boolean) {

    init {
        name = name + " @ JournalDev.com"
        println("Author Name is $name. Is Admin? $isAdmin")
    }
}

הגדרת בנאי הראשי נכנסת לתוך כותרת המחלקה. הגדרנו את סוגי המאפיינים (val/var) בתוך הבנאי עצמו. שים לב: אלא אם כן צוין כ-var, לברירת מחדל, ארגומנטים של הבנאי הם val.

class User(name: String, isAdmin: Boolean)

בקוד למעלה, שם ו-isAdmin לא יכולים להיות משוייכים מחדש. כאחלה, נוכל גם להקצות את ארגומנטי הבנאי לתכונות החבר במחלקה כפי שמוצג למטה.

class User(name: String, val isAdmin: Boolean) {

    var username  = name
    val _isAdmin = isAdmin

    init {
        username= username + " @ JournalDev.com"
        println("Author Name is $name. Is Admin? $_isAdmin")
    }
}

fun main(args: Array) {

    var user = User("Anupam",false)
    user.isAdmin = true //won't compile since isAdmin is val
    user._isAdmin = true //won't compile. Same reason.
    user = User("Pankaj",true)
}

//הדפסה בלוג הקונסול:
//שם המחבר הוא Anupam. האם הוא מנהל? לא
//שם המחבר הוא Pankaj. האם הוא מנהל? כן

ערכי ברירת מחדל של בנאי Kotlin

ב-Kotlin ניתן לציין ערכי ברירת מחדל בבנאי עצמו כפי שמוצג למטה.

class User(name: String, var website: String = "JournalDev") {

    init {
        println("Author $name writes at $website")
    }

    init {
        website = website + ".com"
        println("Author $name writes at $website")
    }
}

fun main(args: Array) {

    var user = User("Anupam","JournalDev")
    user = User("Pankaj","JournalDev")
}

// המשמעות מודפסת על המסך:
// המחבר אנופם כותב ב-JournalDev
// המחבר אנופם כותב ב-JournalDev.com
// המחבר פנקאג' כותב ב-JournalDev
// המחבר פנקאג' כותב ב-JournalDev.com

בנאי משני

בנאים משניים נכתבים בתוך גוף המחלקה על ידי הוספת המילה המפתחית constructor. הדוגמה הבאה מדגימה זאת.

class Student {
    var name: String
    val age : Int

    constructor(name: String, age: Int)
    {
        this.name = name
        this.age = age
    }

    fun printDetails()
    {
        println("Name is $name and Age is $age")
    }

}

fun main(args: Array) {

    var student = Student("Anupam", 24)
    student.printDetails()
}

// המשמעות מודפסת על המסך:
// השם הוא אנופם והגיל הוא 24

השימוש הנפוץ ביותר בבנאים משניים הוא במחלקות משנה כאשר יש צורך לאתחל את המחלקה בדרכים שונות. אם במחלקה קיים בנאי ראשי, הבנאי המשני חייב להתייחס אליו בהצהרתו. ההצהרה נעשית באמצעות המילה המפתחית this.

class Student(var name: String, val age: Int) {

    var skill: String

    init {
        skill = "NA"
    }

    constructor(name: String, age: Int, skill: String) : this(name, age) {
        this.skill = skill
    }

    fun printDetails() {
        if (skill.equals("NA"))
            println("Name is $name and Age is $age")
        else
            println("Name is $name and Age is $age Skill is $skill")
    }
}

// המשמעות מודפסת בלוג:
// השם הוא אנופם והגיל הוא 24
// השם הוא אנופם והגיל הוא 24 Skill is Kotlin

בלוק init משמש לאתחול של חבר המאפיין skill. הבנאי המשני מפנה לבנאי הראשי באמצעות : this.

גטרים וסטרים מותאמים אישית

עד כה, נגשנו ושינינו מאפיינים במחלקה באמצעות אופרטור הנקודה על מופע המחלקה. בואו נשתמש בתחבירי set ו־get כדי לראות איך אפשר להתאים אישית את הגישה.

class Name{
    var post: String = "default"
    set(value) {if(!post.isNotEmpty()) {
        throw IllegalArgumentException(" Enter a valid name")
    }
                field = value
                print(value)
    }

}

fun main(args: Array<String>) {

    var name = Name()
    name.post = "Kotlin Classes"
    name.post = ""
    name.post = "Kotlin Data Classes Our Next Tutorial"


}

הדפס בלוג כולל את הבא:

Kotlin Classes

Exception in thread "main" java.lang.IllegalArgumentException:  Enter a valid name
	at Name.setPost(Test.kt:16)
	at TestKt.main(Test.kt:78)

משתנה ה־field במטמון שומר על הערך הישן. בואו נוסיף גם פונקציה לקבלת ערך.

class Name{
    var post: String = "default"
    set(value) {if(!post.isNotEmpty()) {
        throw IllegalArgumentException(" Enter a valid name")
    }
                field = value
    }
    get() {
        return field.capitalize()
    }

}

fun main(args: Array) {

    var name = Name()
    name.post = "kotlin classes"
    println(name.post)
    name.post = "kotlin data Classes our next Tutorial"
    println(name.post)

}

//הדפס נוסף במהלך הביצוע:
//מחלקות Kotlin
//מחלקות נתונים Kotlin - הדרכה הבאה שלנו

capitalize() משנה את האות הראשונה של המחרוזת לאות גדולה. הערה: אם המאפיין הוא val, פעולת ה־set לא תהיה קומפיל.

מודיפיקטורי הראיון של Kotlin

  • ציבורי: כל מחלקה, פונקציה, מאפיין, ממשק או אובייקט המכיל את המודיפיקטור הזה נראה ונגיש מכל מקום.
  • פרטי: קובץ/פונקציה הוגדרו עם מודיפייר זה יכולים להיכנס רק באותו קובץ. חבר/מאפיין בקובץ/פונקציה עם מודיפייר זה יכולים להיכנס רק בתוך הבלוק הזה.
  • מוגן: מודיפייר זה זהה לפרטי, רק שהוא מאפשר גישה וראות בתת-מחלקות.
  • פנימי: קובץ/ממשק/פונקציה עם מודיפייר זה נגיש רק בתוך אותו מודול.

מודיפיירים לראות גם בבנאי. הקצאת מודיפייר לבנאי ראשי מחייבת אותנו לציין את המילה המפתחת constructor לצד הבנאי בכותרת המחלקה.

class Student private constructor (var name: String, val age: Int) {

    var skill: String

    init {
        skill = "NA"
    }

    constructor(name: String, age: Int, skill: String) : this(name, age) {
        this.skill = skill
    }

    fun printDetails() {
        if (skill.equals("NA"))
            println("Name is $name and Age is $age")
        else
            println("Name is $name and Age is $age Skill is $skill")
    }
}

fun main(args: Array) {

    var student = Student("Anupam",24,"Kotlin")
    student.printDetails()
}

//prints
//השם הוא אנופם והגיל הוא 24, המיומנות היא Kotlin

בנאי פרטי אינו יכול להיקרא מחוץ לקובץ. בקוד לעיל, נוכל ליצור את המחלקה בפונקציה שונה רק באמצעות בנאי משני.

מחלקה אבסטרקטית ב-Kotlin

כמו ב-Java, מילת המפתח abstract משמשת להגינוי של מחלקות אבסטרקטיות ב-Kotlin. מחלקה אבסטרקטית אינה יכולה להיצור ישירות, אך יש אפשרות לשוחזר אותה על ידי מחלקות מורשות. ללא ציון נוסף, החברים של מחלקה אבסטרקטית הם לא אבסטרקטיים.

abstract class Person(name: String) {

    init {
        println("Abstract Class. init block. Person name is $name")
    }

    abstract fun displayAge()
}

class Teacher(name: String): Person(name) {

    var age : Int

    init {
        age = 24
    }

    override fun displayAge() {
        println("Non-abstract class displayAge function overridden. Age is $age")
    }
}

fun main(args: Array) {

    val person = Teacher("Anupam")
    person.displayAge()

}

//הדפסה בקונסול:
//מחלקה אבסטרקטית. בלוק init. שם האדם הוא אנופם
//מחלקה לא אבסטרקטית. הגיל הוא 24

הערה: כיתות המופעלות נפתחות כבר כברירת מחדל. לכן, להוסיף את המילה השמורה "open" כדי לאפשר תת-קבוצות אינו נדרש. מילת המפתח "override" משמשת לדריסת שיטה בתת-קבוצה. כבר כיסינו את היסודות של כיתות Kotlin במדריך זה. עדיין יש עוד הרבה דברים כמו כיתות נתונים, כיתות מוחתמות, ירושה וכו '. אנו נכסה אותם במדריכים הבאים. מקורות: Kotlin Docs

Source:
https://www.digitalocean.com/community/tutorials/kotlin-class-constructor