مفهوم وراثت در شی گرایی

در این جلسه می خواهیم در مورد مفهوم وراثت در شی گرایی حرف بزنیم که یکی از جالب ترین و پر کاربردترین بحث ها در شی گراء(Object Oriented Programming) می باشد و در ادامه به عملکرد تابع سازنده در وراثت می پردازیم. تا اخر مبحث با ما همراه باشید.

همان طوری که در دنیای واقعی هم وراثت را داریم، وراثت در شی گرایی هم داریم. برای درک این مفهوم چند تا کلاس با نام گذاری های ساده ایجاد می کنیم: ClassA, ClassB, ClassC

class ClassA

{

private int ID;
public string Name;
public void Show1()
{

 }

private void Show2()
{

}

}

الان می خواهیم یک کلاس دیگری ایجاد کنیم که از ClassA ارث بری کند:

class ClassB:ClassA

//….برای اینکه یک کلاس از کلاس دیگری ارث ببرد از علامت : استفاده می کنیم
{

}

نکته ای که دارد ما نمی توانیم وراثت چندگانه داشته باشیم یعنی اینکه یک کلاس همزمان از دو کلاس ارث ببرد بدین شکل:

ClassB : ClassA ,ClassC

داخل پنجره ی فرم شده و کنترل Button را روی آن قرار می دهیم می خواهیم از ClassB یک نمونه بسازیم:

مفهوم وراثت در شی گرایی

Name , Show1 بهش دسترسی داریم امّا ID, Show2 چون private است بهش دسترسی نداریم چون خصوصی آن کلاس است .

نکته: سطح دسترسی private توی ارث بری شرکت نمی کند. اگر بخواهیم یک فیلدی را داخل ClassA تعریف کنید که به صورت خصوصی رفتار کند یعنی هیچ کسی به آن دسترسی نداشته باشد امّا توی ارث بری شرکت کند از سطح دسترسی protected استفاده می کنید.

class ClassA
{

private int ID;
public string Name;
protected string LastName;
public void Show1()
{

}
private void Show2()
{

}

}

داخل پنجره ی فرم شده می خواهیم از ClassB یک نمونه بسازیم.

مفهوم وراثت در شی گرایی

چرا LastName را مشاهده نمی کنیم چون به صورت protected است.

protected : بیرون کلاس به صورت خصوصی رفتار می کند و به آن دسترسی نداریم امّا داخل کلاس بهش دسترسی داریم.

class ClassB:ClassA

{

public void ST()
{
Name = “Mahdi”;
LastName = “Nikkhah”;
}

}

پس مشاهده می کنید که داخل کلاس به فیلد LastName دسترسی داریم امّا فیلد ID را نداریم.

 پس نتیجه می گیریم که public و protected توی ارث بری شرکت می کنند امّا private توی ارث بری شرکت نمی کند.

یک کلاس دیگر ایجاد می کنیم:

class ClassC : ClassB
{

public void ST1()
{
Name = “Mahdi”;
LastName = “Nikkhah”;
}

}

مشاهده می کنید فیلدهایی که اصلا داخل ClassB هم نیستند امّا از ارث بری از ClassA به آن رسیده حتی به آن ها هم دسترسی داریم.

عملکرد تابع سازنده در وراثت در شی گرایی

در جلسه پنجم آموزش شی گرایی با متد سازنده آشنا شدیم در این قسمت می خواهیم در مورد نحوه ظاهر شدن سازنده داخل وراثت در شی گرایی توضیح دهیم.

دو تا کلاس به نام های A و B ایجاد می کنیم:

class ClassA
{
private int ID;
}

//—————————-
class ClassB
{
private string Name;
}

اگر بخواهم از کلاس B یک نمونه بسازم هیچ مشکلی نیست:

private void button1_Click(object sender, EventArgs e)
{
ClassB b = new ClassB();
}

اگر کلاس B از کلاس A ارث بری کند:

class ClassA
{
private int ID;
}

//—————————-
class ClassB:ClassA
{
private string Name;
}

باز هیچ مشکلی نیست و من براحتی می توانم از کلاس B نمونه بسازم:

private void button1_Click(object sender, EventArgs e)
{
ClassB b = new ClassB();
}

امّا اگر کلاس A که کلاس پایه می باشد تابع سازنده ای داشته باشد:

مفهوم وراثت در شی گرایی

Error می دهد میگوید کلاس A یک سازنده ای دارد که باید کلاس B آن را تأمین کند.

دیگر نمی توانید از کلاس B نمونه سازی کنید مگر اینکه تابع سازنده کلاس A که کلاس پایه است را تأمین کنید.

برای این کار:

یک سازنده برای کلاس B می نویسیم و ورودی آن را ID قرار می دهیم و ID را پاس می دهیم به سازنده کلاس A ، چطوری؟؟

برای این کار علامت : را بعد از پرانتز می گذاریم و ID را با استفاده از کلمه ی کلیدی base به داخل کلاس A پاس می دهیم.

public ClassB(int ID) : base (ID)
//….پاس دادن
{

}

class ClassA
{
private int ID;
public ClassA(int ID)
{
this.ID = ID;
}
}

//———————————————————-

class ClassB:ClassA
{
private string Name;
public ClassB(int ID):base (ID)
{

     }
}

الان برای نمونه ساختن از کلاس B باید حداقل ID را مقدار دهی کنم:

private void button1_Click(object sender, EventArgs e)

{
ClassB b = new ClassB(20);
}

نکته: پس برای اینکه بتوانیم از کلاس B نمونه بسازیم باید بتوانیم حداقل یکی از توابع سازنده کلاس A را پیاده سازی کنیم

حالا اگر بخواهم داخل کلاس B یک تابع سازنده هم داشته باشم که علاوه بر اینکه ID کلاس A را مقدار دهی کند می خواهم Name را هم مقدار دهی کند

class ClassA
{

private int ID;
public ClassA(int ID)
{
this.ID = ID;
}

}
//—————————-

class ClassB:ClassA

{

private string Name;
public ClassB(int ID):base (ID)
{

}

public ClassB(int ID,string Name) : base(ID)
{
this.Name = Name;
}

}

ID را پاس دادیم به کلاس پایه بدون اینکه کاربر اصلاً متوجه شود که ID داخل کلاس B وجود ندارد.

مفهوم وراثت در شی گرایی

مفهوم وراثت در شی گرایی

الان مشاهده می کنیم که کلاس B دو تا تابع سازنده دارد. حالا اگر یک کلاس دیگه هم داشته باشیم که از کلاس B ارث ببرد.

class ClassA
{

private int ID;
public ClassA(int ID)
{
this.ID = ID;
}

}

//—————————-

class ClassB:ClassA
{

private string Name;
public ClassB(int ID):base(ID) { }
public ClassB(int ID,string Name) : base(ID) { this.Name = Name; }

}

//—————————————

class ClassC : ClassB
{

private string LastName;
public ClassC(int ID) : base(ID) { }
public ClassC(int ID, string Name) : base(ID, Name) { }
public ClassC (int ID,string Name,string LastName): base(ID,Name)

       {
this.LastName = LastName;
}
}

این کلاس هایی که الان نوشتیم برای این بود که چگونه بتوانیم توابع سازنده داخل ارث بری را کنترل می شوند.

ترتیب اجرا شدن سازنده ها به چه صورتی است؟

داخل تمام سازنده ها MessageBox قرا می دهیم تا ترتیب اجرا شدن سازنده ها را مشاهده کنیم .

class ClassA
{

private int ID;
public ClassA(int ID)
{
this.ID = ID;
MessageBox.Show(“Class A “);
}

}

//—————————-

class ClassB:ClassA
{

private string Name;
public ClassB(int ID):base(ID) { MessageBox.Show(“Class B “); }
public ClassB(int ID,string Name) : base(ID)
{
this.Name = Name;
MessageBox.Show(“Class B “);
}

}

//—————————————

class ClassC : ClassB
{

private string LastName;
public ClassC(int ID) : base(ID) { MessageBox.Show(“Class C”); }
public ClassC(int ID, string Name) : base(ID, Name)

{
MessageBox.Show(“Class C “);
}
public ClassC (int ID,string Name,string LastName): base(ID,Name)
{
this.LastName = LastName;
MessageBox.Show(“Class C “);
}

}

ابتدا از ClassA یک نمونه می سازیم:

private void button1_Click(object sender, EventArgs e)
{
ClassA b = new ClassA (1);
}

برنامه را اجرا می کنیم

وراثت در شی گرایی

هم اکنون از ClassB یک نمونه می سازیم:

private void button1_Click(object sender, EventArgs e)
{
ClassB b = new ClassB (1);
}

برنامه را اجرا می کنیم:

وراثت در شی گرایی

مشاهده می کنیم که ابتدا سازنده کلاس پایه اجرا می شود و بعد OK را می زنیم:

وراثت در شی گرایی

و الان سازنده کلاس B اجرا شد

از ClassC یک نمونه می سازیم:

private void button1_Click(object sender, EventArgs e)

{
ClassC b = new ClassC (1);
}

برنامه را اجرا می کنیم:

وراثت در شی گرایی

مشاهده می کنیم که ابتدا سازنده کلاس پایه اجرا می شود و بعد OK را می زنیم:

وراثت در شی گرایی

سازنده کلاس B اجرا شد:

وراثت در شی گرایی

و الان سازنده کلاس C اجرا شد.

پس سازنده ها از پایین به بالا اجرا می شوند و در وراثت هم شرکت نمی کنند یعنی از کلاس پایه اجرا می شوند . امّا توابع مخرب برعکس است از بالا به پایین اجرا می شوند یعنی ابتدا کلاس C بعد کلاس B و بعد کلاس A

 

امیدواریم با وراثت در شی گرایی و نحوه ظاهر شدن متد سازنده در ارث بری به خوبی آشنا شده باشید و بتوانید در برنامه ها از آن استفاده کنید.