مقدمه
وراثت، بین کلاسهای والد (Parent) و فرزند (Child) ارتباط ایجاد میکند. در این مطلب، با یک مثال ساده، نکات مختلفی را بررسی خواهیم کرد.
در ابتدا کلاسهایی را با نام parent و child، به شکل زیر ایجاد میکنیم:
public class Parent
{
public Parent()
{
Console.WriteLine("Parent Constructor");
}
public void Print()
{
Console.WriteLine("Parent Print");
}
}
public class Child : Parent
{
public Child()
{
Console.WriteLine("Child Constructor");
}
public void Print()
{
Console.WriteLine("Child Print");
}
}
با کامپایل کد فوق، هشدار (نه خطا) زیر توسط ویژوال استودیو صادر خواهد شد:
هشدارفوق این نکته را تذکر میدهد که متد Print تعریف شده در کلاس Child، پیاده سازی متد Print را در کلاس والد، مخفی (Hide) میکند. به همین خاطر پیشنهاد میکند که اگر واقعا قصد چنین کاری را داریم (نادیده گرفتن پیاده سازی print کلاس والد) از کلمه کلیدی (keyword) new استفاده کنیم. بدین شکل:
public new void Print()
{
Console.WriteLine("Child Print");
}
حال با نمونه سازی کلاسهای فوق، رفتار سازنده و متد Print را بررسی میکنیم:
Console.WriteLine("====Parent====");
Parent parent = new Parent();
parent.Print();
Console.WriteLine("====Child====");
Child child = new Child();
child.Print();
Console.WriteLine("====Parent Via Child====");
Parent pc = new Child();
pc.Print();
در قسمت اول نمونه سازی از والد، نکته خاصی وجود ندارد. در ابتدا سازنده و سپس فراخوانی متد Print اتفاق خواهد افتاد.
در قسمت دوم نمونه سازی از فرزند، ابتدا سازنده والد و سپس سازنده فرزند فراخوانی خواهند.
در بخش سوم، یک نمونه فرزند را از نوع والد، ایجاد کردهایم .( () Parent pc=new Child). در این بخش ابتدا سازنده والد و بعد از آن سازنده فرزند، فراخوانی میشود و با فراخوانی متد Print، متد والد اجرا خواهد شد.
استفاده از Virtual و Override
اگر بدنبال این باشیم که در قسمت سوم متد Print فرزند فراخوانی شود، مفاهیم virtual و override به کمک ما خواهند آمد:
public class Parent
{
public Parent()
{
Console.WriteLine("Parent Constructor");
}
public virtual void Print()
{
Console.WriteLine("Parent Print");
}
}
public class Child : Parent
{
public Child()
{
Console.WriteLine("Child Constructor");
}
public override void Print()
{
Console.WriteLine("Child Print");
}
}
با تعریف متد از نوع virtual، امکان تحریف رفتار پیش فرض متد را توسط فرزندها، مهیا خواهیم کرد. فرزندان نیز با override کردن متد والد، پیاده سازی خود را اعمال میکنند.
اگر خروجی کد بالا را با قسمت قبل مقایسه کنید، متوجه خواهید شد که در قسمت سوم فرزند، رفتار متد والد را تحریف/بازنویسی (override) کرده است ( پیاده سازی فرزند اجرا شده است).
سازندههای استاتیک (Static Constructor)
سازندههای استاتیک برای مقدار دهی به دادههای استاتیک و یا انجام عملیاتی که تنها قرار است یکبار انجام شوند مورد استفاده قرار میگیرند. این سازندهها بصورت اتوماتیک قبل از ساخت نمونه و مقداردهی اعضای استاتیک و قبل از سازندههای غیر استاتیک اجرا میشوند.
public class Parent
{
static Parent()
{
Console.WriteLine("Parent static Constructor");
}
public Parent()
{
Console.WriteLine("Parent Constructor");
}
public virtual void Print()
{
Console.WriteLine("Parent Print");
}
}
public class Child : Parent
{
static Child()
{
Console.WriteLine("Child static Constructor");
}
public Child()
{
Console.WriteLine("Child Constructor");
}
public override void Print()
{
Console.WriteLine("Child Print");
}
در بخش سوم در ابتدا سازنده استاتیک فرزند و سپس سازنده استاتیک والد فراخوانی خواهند شد و ترتیب اجرای سایر متدها و سازندهها مثل قبل است.
جمع بندی
* اگر نمونهای از یک فرزند را ایجاد کنیم، ابتدا سازندهی والد فراخوانی خواهد شد و پس از آن سازندهی کلاس فرزند.
* اگر قصد تحریف رفتار متد والد را در فرزندان داریم، میتوانیم این متدها را در کلاس والد بصورت virtual تعریف کنیم.