Inheritance-SubClass
در برخی از اوقات، نوشتن چندین کلاس، و بالطبع نوشتن چندین متد لازم میشود، اما با استفاده از مفهوم وراثت میتوان از نوشتن چند باره‌ی کلاسها و متدهای یکسان جلوگیری کرد، اگر خاطرتان باشد، مفهوم شئ گرایی برای پرهیز از تکرار و نوشتن کدهایی پویا به وجود آمده، یکی از این مفاهیم که کاربردی اساسی را در برنامه‌نویسی به عهده دارد وراثت و ساخت SubClass میباشد،در ادامه همراه باشید.
فرض کنید یک کلاس داریم به نام پدر ، که شامل خصوصیات بدیهی یک شخص میباشد، مثل راه رفتن، حرف زدن ، دویدن و ...
همچون قبل میدانیم که حرف زدن و راه رفتن شامل متدهای کلاس پدر میشود، پس کلاس زیر را میسازیم:
 
٭ تمامی کدها و مثال ها را می توانید در بخش playground تست کنید.
class father {
    init(){
        print("New person Object Initialized")
    }   
    func talk(){
        print("I want Say SomeThing")
    }
    func walk (){
        print("I'm Walking")
    }
     func run(){
        print("I'm Running")
    }
}
همانطور که گفتیم، کلاسی به نام father ساخته ایم که شامل اعمالی مثل حرف زدن، راه رفتن و دویدن میشود. اما قبل از اینکه به ساخت کلاس فرزند برسیم خوب است بدانید که اگر بخواهید، در یک کلاس، از متدی درون همان کلاس استفاده کنید، باید از کلیدواژه‌ی self استفاده کنید، برای مثال اگر بخواهیم در متد ()walk، متد ()run را نیز فراخوانی کنید، باید متد ()walk به صورت زیر تغییر دهید:
 func walk (){
        print("I'm Walking")
        self.run()
    }
همانطور که مشاهده میکنید با نوشتن دستور self لیستی از متدهای داخلی (همان) کلاس برای شما باز میشود، که شما میتوانید  از این لیست متد مورد نظر خودرا فراخوانی کنید.مطابق تصویر زیر:
(برای مشاهده تصویر در اندازه واقعی روی آن کلیک کنید)
self-methods
همچون قبل، علامت M به معنای Method میباشد همچنین واژه‌ی Void به ما یادآور میشود که متدهای ()run(),talk و ()walk خروجی محاسباتی ندارند.
پس تا به اینجای کار کلاس father به شکل زیر خواهد بود :
٭ تمامی کدها و مثال ها را می توانید در بخش playground تست کنید.
class father {
    
    init(){
        print("New person Object Initialized")
    }
    
    func talk(){
        print("I want Say SomeThing")
    }
    
    func walk (){
        print("I'm Walking")
        self.run()
    }
    
    func run(){
        print("I'm Running")
    }
}
پس متد ()walk  باعث فراخوانی متد ()run نیز خواهد شد.
نکته: توجه کنید در هنگام نوشتن این دستورات درون محیط playground عبارت import UIKit را از ابتدای دستورات حذف نکنید.
در ادامه میخواهیم کلاس فرزندی از کلاس father بسازیم، که به آن اصطلاحا SubClass گفته میشود،این کار باعث میشود تمامی خصوصیات کلاس پدر(متدها و پراپرتی ها) به کلاس فرزند نیز منتقل شود.نام کلاس فرزند را child انتخاب میکنیم تا مفهوم بیشتری داشته باشد، به صورت زیر کلاس فرزند ساخته میشود:
class child:father{
    
}

قالب کلی کلاس بالا به صورت زیر میباشد:

class نام کلاس والد : نام کلاس فرزند{
}
با استفاده از دستورات بالا توانستیم کلاسی بسازیم به نام child که در اصل کلاس فرزندی است از کلاس father ، به این ترتیب پس از ساخت شی از کلاس فرزند میتوانیم متدهای آنرا مشاهده کنیم که در اصل آنها را از کلاس پدر به ارث برده است،به صورت زیر از کلاس فرزند یک شئ میسازم:
(برای مشاهده تصویر در اندازه واقعی روی آن کلیک کنید)
Child-Class
پس توانستیم کلاسی بنویسیم که تمامی متدها‌ی پدر را دارا میباشد،اما این بدان معنا نیست که کلاس فرزند تماما به متدهای پدر وابسته است، این کلاس میتواند متدها و پراپرتی های خاص خودرا دارا باشد.میتوان همچون سابق متدهارا درون بدنه‌ی کلاس اضافه کرد:
class child:father{
    
    func think(){
        print("i'm thinking ... ")
    }
}
باساخت این متد، کلاس فرزند علاوه بر دسترسی به متدهای والد، میتواند به متد های  مستقل خود نیز دسترسی داشته باشد،این عمل برای پراپرتی ها نیز صادق است.
توجه داشته باشید اگر نام متد ساخته شده برابر با نام یکی از funcهای کلاس والد باشد ،خطا رخ خواهد داد، مگر اینکه بخواهید آنرا بازنویسی کنید، برای اینکار باید از کلیدواژه‌ی override استفاده کنید. مثال زیر را مشاهده کنید :
 class child:father{   
    func think(){
        print("i'm thinking ... ")
    }
    override func run() {
        print("I'm Running Faster than my father !")
    }
}
اما اگر بخواهیم متدی از کلاس پدر درون کلاس فرزند اجرا شود باید از کلیدواژه‌ی super استفاده کنید، همچون مثال زیر:
class child:father{
    
    func think(){
        print("i'm thinking ... ")
        super.talk()
    }
    override func run() {
        print("I'm Running Faster than my father !")
    }
    
}
در کلاس فرزند، و درون متد ()think با استفاده از کلیدواژه‌‌ی super متد ()talk کلاس پدر را فراخوانی کردیم، پس بدین ترتیب پس از فراخوانی متد ()think کلاس فرزند (بعد از ساخت شئ از این کلاس)، ابتدا پیغام ... i'm thinking چاپ میشود، سپس متد درون کلاس پدر به نام ()talk فراخوانی شده و مقدار 
I want Say SomeThing در زیر پیغام قبلی چاپ میشود.دستورات نوشته شده تا به الان به صورت زیر میباشد:
 
٭ تمامی کدها و مثال ها را می توانید در بخش playground تست کنید.
class father {
    
    init(){
        print("New person Object Initialized")
    }
    func talk(){
        print("I want Say SomeThing")
    }
    func walk (){
        print("I'm Walking")
        self.run()
    }
    func run(){
        print("I'm Running")
        
    }
}

class child:father{
    
    func think(){
        print("i'm thinking ... ")
        super.talk()
    }
    override func run() {
        print("I'm Running Faster than my father !")
    }
}

var childClass:child = child()
childClass.run()
برای فراخوانی متد ()think کلاس فرزند نیز، باید به صورت زیر اقدام کنید:
childClass.think()
نکته : همانطور که متوجه شدید در کلاس فرزند وجود متد ()init اجباری نمیباشد.در حقیقت SubClass ها احتیاجی به متد ()init نخواهند داشت ولی اگر بخواهیم متد ()init مستقل در کلاس فرزند داشته باشیم، باید مثل قبل آنرا override یا دوباره نویسی کنیم، ولی اگر بخواهید در متد ()init فرزند متد ()init والد را نیز فراخوانی کنیم باید با کلید واژه‌ی super، قبلاً آنرا فراخوانی کنیم، به صورت زیر:
  class child:father{
    
    override init() {
        super.init()
    }
    func think(){
        print("i'm thinking ... ")
        super.talk()
    }
    override func run() {
        print("I'm Running Faster than my father !")
    }
    
}
برای یادگیری بهتر ، کلیدواژه های این جلسه را دوباره توضیح میدهم:

self : زمانی کاربرد دارد که بخواهید متدی را درون متدی دیگر، درون یک کلاس واحد فراخوانی کنید.مثال :

self.walk()

override : زمانی کاربرد دارد که بخواهید یک متد را با نامی تکراری، دوباره بازنویسی کنید.مثال :

override func run() {
        print("I'm Running Faster than my father !")
}
نکته : زمانی میتوانید از کلیدواژه‌ی override استفاده کنید که قبلا با همان نام، متدی در همان کلاس یا کلاس والد وجود داشته باشد.

super : زمانی که بخواهید متدی را از کلاس والد درون کلاس فرزند فراخوانی کنید باید از این کلیدواژه استفاده شود. مثال :

func think(){
        print("i'm thinking ... ")
        super.talk()
    }
چالش : برای کلاسهای father و child پراپرتی‌هایی را بسازید که بتواند مقدار نام و نام خانوادگی آنها را ذخیره کند،توجه کنید، نام خانوادگی باید به فرزند ارث رسیده باشد.
نکته :دوستان عزیز، اگر در طول آموزش به سوالی برخورد کردید، لطفا برای بهتر شدن آموزشها همچنین برای بهره بردن دیگر دوستان، حتما در بخش نظرات سوال خود را مطرح کنید، و من تلاش خواهم کرد، در اسرع وقت به سوالات شما پاسخ دهم.
با تشکر.