آموزش وراثت و ارث بری سی شارپ
بعد از معرفی بحثهای مختلف دربارهی برنامه نویسی شی گرا در سی شارپ به اصلیترین بخش آن میرسیم. در این بخش به بررسی وراثت و ارث بری در سی شارپ میپردازیم.
حتما قبل از بررسی وراثت و ارث بری نوشتهی مطالب قبلی این دورهی آموزشی را با هشتگ #دوره آموزشی_سی_شارپ در سایت ما را مطالعه کنید.
آموزش وراثت و ارث بری سی شارپ
معرفی Inheritance (وراثت، ارثبری)
مفهوم Inheritance یکی از اصول بنیادی برنامهنویسی شیگرا است که موجب ساخت کلاسها بهصورت سلسلهمراتبی میشود. که با استفاده از inheritance میتوانید یک کلاس کلی با یک سری ویژگی تعریف کنید. که این ویژگیها میتوانند در تعدادی بخش مرتبط باهم، مشترک شوند. این کلاس کلی، میتواند توسط کلاسهای دیگر، ارثبری شود و مواردی که یکتاست را در اختیار آنها قرار دهد. کلاسی که از آن ارثبری میشود، base class (کلاس پایه) نام دارد و کلاسی که ارثبری را انجام میدهد derived class (کلاس مشتق شده) نامیده میشود. derived class نسخهی اختصاصی شدهی base class است. derived class تمام variableها، methodها، propertyها و indexerهای تعریف شده در base class را به ارث میبرد و در کنار اینها عناصر مخصوص به خود را نیز اضافه میکند.
مثال:
class Animal { public bool Mammal; public string Color; public int Weight; public string Gender; public void Greet() { Console.WriteLine("The Animal says hello!"); } public void Talk() { Console.WriteLine("The Animal Talk!"); } public void Eat() { Console.WriteLine("The Animal Eat!"); } }
در کلاس Animal تعدادی متد و متغیر میبینید که میتواند در همهی حیوانات مشترک است. این کلاس را بهعنوان base class در نظر میگیریم. در مرحلهی بعد کلاس Dog عناصر این base class را به ارث میبرد.
دقت کنید که کلاس Dog را چگونه تعریف میکنیم:
class Dog : Animal { public string DogType { get; set; } public string Name { get; set; } public void Show() { Console.WriteLine(Name + " is barking!"); } }
کلاس Dog نوع خاصی از کلاس Animal را میسازد. کلاس Dog شامل همهی موارد تعریف شده در کلاس Animal است و علاوهبر آنها، دو فیلد و یک متد اضافهتر نیز دارد.
class Animal { public string Color { get; set; } public int Weight { get; set; } public string Gender { get; set; } public int Age { get; set; } public void Greet() { Console.WriteLine("The Animal says hello!"); } public void Talk() { Console.WriteLine("The Animal Talk!"); } public void Eat() { Console.WriteLine("The Animal Eat!"); } } class Dog : Animal { public string Breed { get; set; } public string Name { get; set; } public void Bark() { Console.WriteLine(Name + " is barking!"); } } // Using : Dog dog = new Dog(); dog.Breed = "Brittany"; dog.Name = "Ace"; dog.Gender = "Male"; dog.Weight = 10; dog.Color = "White"; dog.Age = 1; dog.Talk(); dog.Eat(); dog.Greet(); dog.Bark();
اینکه چند مرحله ارثبری انجام شود، مهم نیست. مانند public و private، دسترسی protected در این مراحل ارثبری، همواره برای یک عضو، protected میماند. از اینرو، هنگامی که یک derived class بهعنوان یک base class برای یک derived class دیگر مورد استفاده قرار میگیرد. تمام اعضای protected در اولین base class که توسط اولین derived class ارثبری شدهاند. در دومین derived class نیز بهصورت protected ارثبری میشوند. با وجود اینکه دسترسی protected بسیار مفید است، در همهی موقعیتها نباید از آن استفاده کرد. فقط باید زمانی از آن بهره برد که میخواهیم یک عضو در سلسهمراتب ارثبری قابل دسترس، و در خارج از این سلسلهمراتب، غیر قابل دسترسی است.
Constructor ها و ارثبری
در سلسلهمراتب ارثبری، هم base class ها و هم derived classها میتوانند constructor خودشان را دارند.
کدام constructor مسئول ساختن شیء derived class است؟
در واقع، constructorای که در base class قرار دارد، بخش base class یک شیء و constructorای که در derived class واقع است. قسمت derived class را میسازد. زیرا base class هیچ دسترسی و اطلاعی از عناصر درون derived class ندارد.
از اینرو construction آنها باید جداگانه شود:
class A { protected int ID { get; set; } protected int Number { get; set; } } class B : A { protected string Name; public B(int id, int number, string name) { ID = id; Number = number; Name = name; } public void Show() { Console.WriteLine(Name + ": " + ID + " - " + Number); } } // Using : B ob1 = new B(180, 1, "Filipe"); ob1.Show(); B ob2 = new B(190, 2, "Cevat"); ob2.Show();
فراخوانی constructorهای base class
یک derived class میتواند constructorای که در base classاش تعریف شده است را از طریق گسترش دادن فرم constructor در derived class و کلمهی کلیدی base، صدا بزند.
فرم کلی تعریف گسترش یافتهی آن بهشکل زیر است:
derived-constructor(parameter-list) : base(arg-list) { // body of constructor }
در اینجا، arg-list مشخصکنندهی argumentهای مورد نیاز constructor در base class است. به نحوهی قرار گرفتن نیز توجه کنید.
class A { private int i, j; public A(int a, int b) { i = a; j = b; } public void ShowA() { Console.Write(i + " " + j); } } class B : A { private int k; public B(int a, int b, int c) : base(a, b) { k = c; } public void ShowB() { ShowA(); Console.WriteLine(" " + k); } }
به مثال زیر دقت کنید:
class A { private int i, j; public A(int a, int b) { i = a; j = b; } public A(int a) { i = j = a; } public void ShowA() { Console.Write(i + " " + j); } } class B : A { private int k; public B(int a, int b, int c) : base(a, b) { k = c; } public B(int a) : base(a) { k = 5; } public void ShowB() { ShowA(); Console.WriteLine(" " + k); } } // Using : B b1 = new B(2, 4, 6); b1.ShowB(); B b2 = new B(1); b2.ShowB();
در این مثال، base class شامل دو constructor بوده که constructor دوم آن شامل یک argument است. بنابراین هنگامیکه در کلاس B از base استفاده میکنید و یک argument به آن میدهید. در A آن constructor که یک parameter دارد اجرا خواهد شد. هنگامیکه یک derived class از کلمهیکلیدی base استفاده میکند، base مستقیماً به نزدیکترین base class بالای derived class مربوط میشود. از اینرو، هنگامیکه از سلسله مراتب ارثبری استفاده میکنید، base به نزدیکترین base class در این زنجیره، رجوع خواهد کرد. اگر از base استفاده نکنید، constructor پیشفرض base class اجرا خواهد شد. کاربرد دوم آن برای دسترسی به اعضایی از base class است که به دلیل تشابه اسمی در derived class قابل مشاهده نیستند. derived class میتواند عضوی را تعریف کند که مشابه نام یکی از اعضای base classاش است. آن عضو base class در derived class دیده نمیشود. درحالیکه این مورد از لحاظ تکنیکی در سیشارپ خطا شمرده نمیشود، کامپایلر یک پیغام هشدار به شما داده و از اینکه یکی از اعضا دیده نمیشود، شما را باخبر میسازد. اگر قصد شما این است تا باعث دیده نشدن یکی از اعضای base class شوید، بهمنظور رفع هشدار کامپایلر، در derived class در تعریف آن عضو از کلمهیکلیدی new استفاده کنید. دقت کنید که اینطور استفاده از new با آن حالتی که از آن برای ساختن شیء استفاده میکردید، متفاوت است.
مثال:
class A { public int i = 0; } class B : A { new int i; // this i hides the i in A public B(int b) { i = b; // i in B } public void Show() { Console.WriteLine("i in derived class: " + i); } } // Using : B ob = new B(2); ob.Show();
به نحوهی استفادهی new توجه کنید:
new int i; // this i hides the i in A
این خط کد به کامپایلر میگوید که شما میدانید متغیر جدیدی به اسم i ساخته شده است و باعث دیده نشدن i در base class خواهد شد. اگر new را از کد بالا حذف کنید، پیغام هشدار compiler را مشاهده خواهید کرد. از آنجا که B متغیر i خودش را تعریف میکند. باعث دیده نشدن i در A میشود، پس از اجرای متد ()Show، مقدار متغیر i که متعلق به B است نمایش داده خواهد شد، نه مقدار i در متغیر A. استفاده از base برای دسترسی به اعضایی که دیده نمیشوند دومین استفاده از base تا حدودی شیبه به this است با این تفاوت که base همیشه به base class رجوع میکند.
نحوهی استفاده از base به شکل زیر است:
base.member
در اینجا، member هم میتواند متغیر و هم میتواند متد شود. این نحوهی استفاده از base برای مواقعی است که یک عضو در base class به دلیل تشابه اسمی در derived class دیده نمیشود.
به مثال زیر توجه کنید:
class A { public int i = 0; } class B : A { new int i; // this i hides the i in A public B(int a, int b) { base.i = a; // i in A i = b; // i in B } public void Show() { Console.WriteLine("i in base class: " + base.i); Console.WriteLine("i in derived class: " + i); } } // Using : B ob = new B(1, 2); ob.Show();
همانطور که میبینید، با وجود اینکه متغیر i در B باعث دیده نشدن متغیر i در A میشود. با استفاده از کلمهیکلیدی base توانستیم در کلاس B به آن دسترسی پیدا کنیم. این مورد دربارهی متدها نیز صدق میکند.
برای مثال اگر در کد قبل، هردو کلاس متدی به اسم ()Show تعریف کنند با استفاده از base میتوانید در derived class به متد ()Show در base class دسترسی پیدا کنید:
class A { public int i = 0; public void Show() { Console.WriteLine("i in base class: " + i); } } class B : A { new int i; public B(int a, int b) { base.i = a; i = b; } new public void Show() { base.Show(); Console.WriteLine("i in derived class: " + i); } } // Using : B ob = new B(1, 2); ob.Show();
همانطور که میبینید، ()base.Show باعث شده که متد ()Show در base class صدا زده شود. به نحوهی استفاده از new در این مثال، دقت کنید. new در اینجا باعث میشود به کامپایلر بفهمانید که شما میدانید متد ()Show در کلاس B باعث دیده نشدن ()Show در کلاس A میشود.
لطفا نظرات خودتان را در ارتباط با “وراثت در سی شارپ” برای ما بنویسید تا در تولید دورههای بعدی از نظرات شما استفاده کنیم. خب این جلسه هم به پایان رسید باید به این نکته توجه کنید که مباحث بالا در برنامه نویسی تجاری اهمیت فراوانی دارد. برای استفاده از تمامی جلسات از هشتگ #دوره آموزشی_سی_شارپ در سایت ما استفاده کنید. منتظر جلسهی بعدی دوره آموزشی سی شارپ بمانید.
خیلی عالی و کامل بود ممنون ازتون
مرسی از اینکه نظرتون رو برای ما ارسال کردین. شما میتوانید از قسمت های دیگر دورهی آموزشی سی شارپ نیز استفاده کنید