فئة Kotlin – مُنشئ Kotlin

في هذا الدرس، سنتناول مفاهيم برمجة الكائنات في لغة Kotlin. سنناقش تفصيليًا فصول Kotlin. سنلقي نظرة أيضًا على بناة Kotlin، ووسائط الوصول، والفصول المجردة.

فصل Kotlin

الفصل هو نموذج محدد يجمع بين الوظائف والخصائص. يتم تعريف الفصول في Kotlin باستخدام كلمة الرئيسية class تتبعها اسم الفصل. يتم وضع الجسم داخل الأقواس المنحنية.

class FirstClass {
}

يتم إنشاء مثيل من الفصل بالطريقة التالية:

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

على عكس Java، new ليست كلمة رئيسية في Kotlin. الفصول بشكل افتراضي هي final في Kotlin. لذلك، يبدو ما يعادل النهج أعلاه في Java كما يلي:

public final class FirstClass {
}

وبالتالي، بشكل افتراضي، الفصول في Kotlin غير قابلة للتوريث. لجعل الفصل غير نهائي، نحتاج إلى إضافة كلمة الرئيسية open.

open class Me{
}

تسمح تعليقة open للآخرين بالتورث من هذا الفصل.

مثال على فصل 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 مرة أخرى باستخدام مشغل النقطة.

كوتلن init

يتم تعريف كتلة init لكوتلن كما هو موضح أدناه.

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")
}

//يتم طباعة ما يلي في وحدة التحكم في السجل.
//الكتلة المبدئية الأولى التي تطبع كوتلن
//الكتلة المبدئية الثانية التي تطبع 6

تسمح فئات كوتلن بطباعة الخصائص في التعريف نفسه باستخدام وظيفة 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")
}

//يتم طباعة ما يلي.
//الخاصية الأولى: كوتلن
//الكتلة المبدئية الأولى التي تطبع كوتلن
//الخاصية الثانية: 6
//الكتلة المبدئية الثانية التي تطبع 6

بناء Kotlin

بناء Kotlin هي وظائف أعضاء خاصة تستخدم لتهيئة الخصائص. تختلف بناء Kotlin في الكتابة والهيكل عن Java. بشكل افتراضي، يحتوي الفصل على بناء فارغ كما هو موضح أدناه:

class Student {
    var name: String
    val age : Int

    init {
        name = "Anupam"
        age = 24
    }

    init {
        name = "Anupam Chugh"
        //العمر = 26
    }
}

fun main(args: Array) {
    
    val student = Student()
    println("${student.name} age is ${student.age}")
    student.name = "Your"
    //student.age = 26 // لن يتم ترجمته. العمر هو val
    println("${student.name} age is ${student.age}")

}

//الناتج على الشاشة هو:
//أنوبام تشوغ العمر هو 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)
}

//الناتج في وحدة تسجيل السجلات:
//اسم المؤلف هو أنوبام. هل هو مسؤول؟ خطأ
//اسم المؤلف هو بانكاج. هل هو مسؤول؟ صحيح

قيم البناء الافتراضية في 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

لا يمكن استدعاء المُبنيات الخاصة خارج الفئة. في الشفرة أعلاه، يمكننا تحديد فئة في وظيفة مختلفة فقط باستخدام المُنشئ الثانوي.

فئة كوتلن المجردة

مثل جافا، يُستخدم الكلمة الرئيسية abstract لتعريف الفئات المجردة في كوتلن. لا يمكن تحديد فئة مجردة. ومع ذلك، يمكن أن يتمورث منها الفئات الفرعية. بشكل افتراضي، فإن أعضاء الفئة المجردة غير المجردة ما لم يُحدد خلاف ذلك.

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

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