وراثت در برنامه نویسی کاتلین 

4 سال پیش

وراثت در برنامه نویسی کاتلین 

در این درس از مجموعه درس های آموزش برنامه نویسی سایت سورس باران، به شما در مورد وراثت در برنامه نویسی کاتلین (inheritance in kotlin) خواهیم گفت و به کمک مثال هایی خواهیم گفت که چگونه می توان آن را در کاتلین پیاده سازی کرد.

وراثت یکی از ویژگی های اصلی برنامه نویسی شی گرا است. به کاربر اجازه می دهد تا یک کلاس جدید (کلاس مشتق شده) از یک کلاس موجود (کلاس پایه) ایجاد کند.

کلاس مشتق شده تمام ویژگی ها را از کلاس پایه به ارث می برد و می تواند از ویژگی های اضافی خاص خود باشد.

چرا وراثت؟

فرض کنید، در برنامه خود، سه شخصیت می خواهید – یک معلم ریاضی ، یک فوتبالیست و یک تاجر.

از آنجا که همه شخصیت ها انسان هستند، می توانند راه بروند و صحبت کنند. با این حال، آنها مهارت های خاصی نیز دارند. یک معلم ریاضی می تواند ریاضیات را آموزش دهد، یک فوتبالیست می تواند فوتبال بازی کند و یک تاجر می تواند یک تجارت را اداره کند.

شما می توانید به صورت جداگانه سه کلاس برای آن ایجاد کنید و قابلیت هایی به آن اضافه کنید که می توانند راه بروند، صحبت کنند و مهارت خاص خود را انجام دهند.

وراثت در برنامه نویسی کاتلین 

در هر یک از کلاس ها، شما کد مشابهی را برای راه رفتن و صحبت برای هر شخصیت کپی می کنید.

اگر می خواهید یک ویژگی جدید اضافه کنید – مانند غذا خوردن، باید کد مشابه را برای هر کاراکتر به صورت تک تک پیاده سازی کنید. این می تواند به راحتی مستعد خطا (هنگام کپی) و کدهای تکراری شود.

بسیار آسان تر خواهد بود اگر  کلاس یک Person با ویژگی هایی مانند صحبت کردن، پیاده روی، غذا خوردن، خوابیدن داشته باشیم و مهارت های خاصی را به شخصیت های خود اضافه کنیم. این کار با استفاده از ارث انجام می شود. و روند کار را بسیار راحت تر می کند.

وراثت در برنامه نویسی کاتلین 

با استفاده از وراثت، اکنون کد یکسانی را برای ()walk(). talk() ،eat برای هر کلاس اجرا نمی کنید. شما فقط باید آنها را به ارث ببرید.

بنابراین، برای MathTeacher (کلاس مشتق شده)، شما تمام ویژگی های یک شخص (کلاس پایه) را به ارث می برید و ویژگی جدید teachMath() را اضافه می کنید . به همین ترتیب، برای کلاس فوتبالیست، شما تمام ویژگی های کلاس Person را به ارث می برید و یک ویژگی جدید playFootball () و غیره را اضافه می کنید.

استفاده از وراثت باعث می شود کد شما تمیزتر، قابل فهم باشد و قابلیت بسط پذیری داشته باشد.

لازم به یادآوری است: هنگام کار با وراثت، هر کلاس مشتق شده باید این شرط is a را داشته باشد که آیا “یک کلاس پایه” است یا نه. در مثال بالا، MathTeacher یک کلاس  Person است ، فوتبالیست یک شخص است. اما Businessman یک کلاس مشتق‌شده از Business نیست. شما نمی توانید چیزی مانند این داشته باشید.

وراثت در  کاتلین

بیایید سعی کنیم بحث فوق را به صورت کد اجرا کنیم:

open class Person(age: Int) {
    // code for eating, talking, walking
}

class MathTeacher(age: Int): Person(age) {
    // other features of math teacher
}

class Footballer(age: Int): Person(age) {
    // other features of footballer
}

class Businessman(age: Int): Person(age) {
    // other features of businessman
}

 

در اینجا، Person یک کلاس پایه است و کلاس های MathTeacher ، Footballer و Businessman از کلاس Person مشتق شده اند.

توجه داشته باشید، کلید واژه  open قبل از  آکولاد در Person آمده، مهم است.

به طور پیش فرض کلاس ها در کاتلین final هستند. اگر با جاوا آشنایی دارید، می دانید که کلاس final را نمی توان زیر کلاس کرد. با استفاده از حاشیه نویسی open روی یک کلاس، کامپایلر به شما امکان می دهد کلاسهای جدیدی از آن استخراج کنید.

مثال: وراثت در  کاتلین

open class Person(age: Int, name: String) {
    init {
        println("My name is $name.")
        println("My age is $age")
    }
}

class MathTeacher(age: Int, name: String): Person(age, name) {

    fun teachMaths() {
        println("I teach in primary school.")
    }
}

class Footballer(age: Int, name: String): Person(age, name) {
    fun playFootball() {
        println("I play for LA Galaxy.")
    }
}

fun main(args: Array<String>) {
    val t1 = MathTeacher(25, "Jack")
    t1.teachMaths()

    println()

    val f1 = Footballer(29, "Christiano")
    f1.playFootball()
}

 

خروجی کد به شکل زیر است:

My name is Jack.
My age is 25
I teach in primary school.

My name is Cristiano.
My age is 29
I play for LA Galaxy.

 

در اینجا، دو کلاس MathTeacher و Footballer از کلاس Person مشتق شده است.

سازنده اولیه کلاس Person دو مشخصه age و name  را اعلان کرد و دارای بلوک مقداردهی می باشد. بلوک مقداردهی (و توابع عضو) کلاس پایه Person توسط اشیا  کلاسهای مشتق شده (MathTeacher و Footballer) قابل دسترسی است.

کلاسهای مشتق شده MathTeacher و Footballer به ترتیب  teachMaths() و playFootball () توابع عوض خاصی را برای خود دارند. این توابع فقط از طریق اشیای کلاس مربوطه قابل دسترسی هستند.

وقتی شی t1 کلاس از MathTeacher ایجاد می شود؛

val t1 = MathTeacher(25, "Jack")

 

پارامترها به سازنده اولیه منتقل می شوند. در کاتلین، بلوک init هنگام ایجاد شی فراخوانی می شود. از آنجا که، MathTeacher از کلاس Person مشتق شده است، به دنبال بلوک مقدار دهی اولیه در کلاس پایه (Person) است و آن را اجرا می کند. اگر MathTeacher بلوک init داشت، کامپایلر بلوک init کلاس مشتق شده را نیز اجرا می کرد.

در مرحله بعد، تابع () TeacMaths برای شی t1 با استفاده از دستور t1.teachMaths () فراخوانی می شود.

این برنامه هنگام ایجاد شی f1 از کلاس Footballer به طور مشابه کار می کند. بلوک init کلاس پایه را اجرا می کند. سپس، با استفاده از دستور f1.playFootball () گزاره playFootball () از کلاس Footballer فراخوانی می شود.

 

نکات مهم: وراثت کوتلین

اگر کلاس، سازنده اولیه دارد، مبنا باید با استفاده از پارامترهای سازنده اصلی مقداردهی اولیه شود. در برنامه فوق، هر دو کلاس مشتق شده دارای دو پارامتر  age و name هستند و هر دو این پارامترها در سازنده اولیه در کلاس مبنا مقداردهی می شوند.

مثالی دیگر:

open class Person(age: Int, name: String) {
    // some code
}

class Footballer(age: Int, name: String, club: String): Person(age, name) {
    init {
        println("Football player $name of age $age and plays for $club.")
    }

    fun playFootball() {
        println("I am playing football.")
    }
}

fun main(args: Array<String>) {
    val f1 = Footballer(29, "Cristiano", "LA Galaxy")
}

 

در اینجا سازنده اولیه کلاس مشتق شده دارای ۳ پارامتر و کلاس مبنا دارای ۲ پارامتر است. توجه داشته باشید که هر دو پارامتر کلاس مبنا مقداردهی اولیه می شوند.

در صورت عدم وجود سازنده اولیه، هر کلاس مبنا باید مبنا را مقداردهی کنند یا سازنده دیگری را که این کار را نمایندگی کند. به عنوان مثال،

fun main(args: Array<String>) {

    val p1 = AuthLog("Bad Password")
}

open class Log {
    var data: String = ""
    var numberOfData = 0
    constructor(_data: String) {

    }
    constructor(_data: String, _numberOfData: Int) {
        data = _data
        numberOfData = _numberOfData
        println("$data: $numberOfData times")
    }
}

class AuthLog: Log {
    constructor(_data: String): this("From AuthLog -> + $_data", 10) {
    }

    constructor(_data: String, _numberOfData: Int): super(_data, _numberOfData) {
    }
}

 

Override کردن تابع‌های عضو و مشخصه‌ها

اگر کلاس مینا و کلاس مشتق شده شامل یک تابع عضو (یا خاصیت) با همان نام باشد، می توانید با استفاده از کلید واژه override، تابع عضو کلاس مشتق شده را نادیده بگیرید و از کلید واژه open برای عملکرد عضو کلاس مبنا استفاده کنید.

مثال: Override کردن تابع‌های عضو

// Empty primary constructor
open class Person() {
    open fun displayAge(age: Int) {
        println("My age is $age.")
    }
}

class Girl: Person() {

    override fun displayAge(age: Int) {
        println("My fake age is ${age - 5}.")
    }
}

fun main(args: Array<String>) {
    val girl = Girl()
    girl.displayAge(31)
}

 

خروجی کد به شکل زیر می باشد؛

My fake age is 26.

 

در اینجا ، (girl.displayAge (31 روش ()displayAge  کلاس مشتق شده (girl.displayAge(31 اقدام به فراخوانی ()displayAge می‌کند. امکان override کردن کلاس مبنا به روش مشابه نیز وجود دارد.

// Empty primary constructor
open class Person() {
    open var age: Int = 0
        get() = field

        set(value) {
            field = value
        }
}

class Girl: Person() {

    override var age: Int = 0
        get() = field

        set(value) {
            field = value - 5
        }
}

fun main(args: Array<String>) {

    val girl = Girl()
    girl.age = 31
    println("My fake age is ${girl.age}.")
}

 

خروجی کد به شکل زیر می باشد؛

My fake age is 26.

 

همانطور که مشاهده می کنید، ما به ترتیب از کلمات کلیدی override و open برای خصوصیت age در کلاس مشتق شده و کلاس مبنا استفاده کرده ایم.

فراخوانی اعضای کلاس مبنا از کلاس مشتق شده در کاتلین

شما می توانید با استفاده از کلید واژه super، توابع (و مشخصه های دسترسی) کلاس مبنا را از یک کلاس مشتق شده فراخوانی کنید. نحوه انجام این کار به صورت زیر است:

open class Person() {
    open fun displayAge(age: Int) {
        println("My actual age is $age.")
    }
}

class Girl: Person() {

    override fun displayAge(age: Int) {

        // calling function of base class
        super.displayAge(age)
        
        println("My fake age is ${age - 5}.")
    }
}

fun main(args: Array<String>) {
    val girl = Girl()
    girl.displayAge(31)
}

 

خروجی کد به شکل زیر می باشد؛

My age is 31.
My fake age is 26.

 

منبع

 

لیست جلسات قبل آموزش برنامه نویسی کاتلین

  1. معرفی کاتلین،  Kotlin Hello World – اولین برنامه کاتلین
  2. انواع متغیرهای پایه در کاتلین
  3. عملگرهای برنامه نویسی کاتلین
  4. تبدیل نوع در برنامه نویسی کاتلین
  5. عبارت ها، گزاره ها و بلوک ها در برنامه نویسی کاتلین
  6. کامنت ها در برنامه نویسی کاتلین
  7. ورودی / خروجی پایه در برنامه نویسی کاتلین
  8. عبارت if در برنامه نویسی کاتلین
  9. عبارت when در برنامه نویسی کاتلین
  10. حلقه های while و do … while در برنامه نویسی کاتلین
  11. حلقه for در برنامه نویسی کاتلین
  12. عبارت break در برنامه نویسی کاتلین
  13. عبارت continue در برنامه نویسی کاتلین
  14. توابع در برنامه نویسی کاتلین
  15. فراخوانی تابع میانوندی در برنامه نویسی کاتلین
  16. آرگومان ‌های پیش ‌فرضآرگومان ‌های پیش ‌فرض و نام ‌دار در برنامه نویسی کاتلین
  17. توابع بازگشتی در برنامه نویسی کاتلین
  18. کلاس و شی در برنامه نویسی کاتلین
  19. سازنده ها در برنامه نویسی کاتلین
  20. Getter ها و Setter ها در برنامه نویسی کاتلین

 

0
برچسب ها :
نویسنده مطلب erfan molaei

دیدگاه شما

بدون دیدگاه