Overriding متدها
نام دوره: زبان سی شارپ مقدماتی
نویسنده: علی مقدم جاه (مدرس دوره)
Overriding متدها
چندریختی یا polymorphism در متدها چیست؟
در پست آموزش متد چیست و همچنین پست آموزش وراثت در شئگرایی، با مفاهیم مورد نیاز Overriding متدها آشنا شدید؛ یادتان باشد که مبحث Overriding با مبحث overloading متفاوت بوده که میتوانید در پست آموزشی مربوط به خود مطالعه نمایید.
فرض کنید یک کلاسی داریم به نام Person که به عنوان کلاس والد ازش استفاده میکنیم:
public abstract class Person
{
public int Id { get; set; }
public string FullName { get; set; }
public Person(int id, string fullName)
{
this.StudentId = id;
this.FullName = fullName;
}
public void Print()
{
Console.WriteLine($"id: {Id}\tname: {FullName}");
}
}
این کلاس والد همانطور که مشاهده میکنید، دارای دو پراپرتی به نام id و fullName و یک متد سازنده به همراه یک متد چاپ اطلاعات پراپرتیها است.
حال به سراغ تعریف کلاسهای فرزند میرویم:
public class Student :Person
{
public int StudentCode { get; set; }
public Student(int studentCode, int id, string fullName):base(id, fullName)
{
this.StudentCode = studentCode;
}
}
public class Master :Person
{
public string MasterDegree { get; set; }
public Master(string masterDegree, int id, string fullName):base(id, fullName)
{
this.MasterDegree = masterDegree;
}
}
public class Employee :Person
{
public int EmployeeSalary { get; set; }
public Employee(int employeeSalary, int id, string fullName):base(id, fullName)
{
this.EmployeeSalary = employeeSalary;
}
}
همانطور که میدانید، زمانی که از یک کلاس والد استفاده میکنیم و کلاسهای دیگر را فرزند این کلاس والد قرار میدهیم، در زمان تعریف یک شئ یا نمونه از تمامی کلاسهای فرزند، یک نسخه از عضوهای داخل کلاس والد را برای خود به ارث خواهند برد.
درنتیجه متد Print از طریق تمامی اشیاء و نمونههای تعریف شده از کلاسهای فرزند قابل دسترس میباشد:
class Program
{
public static void Main(string[] args)
{
Student object1 = new Student(100,1,"Ladan Kazemi");
Master object2 = new Master("it",2,"Ali Moghadam Jah");
Employee object3 = new Employee(4500000,3,"Anahita Khosravi");
object1.Print();
object2.Print();
object3.Print();
}
}
در مثال فوق ما ابتدا از هر سه کلاس فرزند، یک نمونه به نامهای object1, object2 و object3 را تعریف کرده و سپس با استفاده از شناسه این نمونههای تعریف شده از کلاس، متد Print داخل کلاس والد یعنی Person را فراخوانی کردیم.
پس متوجه شدید که تمامی کلاسهای فرزند، متد Print نوشته شده درون کلاس والد یعنی Person را به ارث بردهاند.
اما همانطور که در کدهای بالا مشاهده کردید، متد Print تنها قابلیت چاپ id و FullName را دارد!
اما شاید شما بخواهید با فراخوانی متد Print در هر کلاس فرزند، پراپرتیهای داخل آن کلاس فرزند نیز چاپ شوند!
مثلا کلاس Student دارای پراپرتی StudentCode، کلاس Master دارای پراپرتی Degree و کلاس Employee دارای پراپرتی Salary است که خب این متد Print توانایی چاپ این پراپرتیها از اعضا داخلی کلاسهای فرزند را ندارد.
به همین منظور میتوانیم از مبحث شیرین Overriding متدها استفاده کنیم.
Overriding متدها یعنی دوباره نویسی متد موجود در کلاس والد، داخل کلاس فرزندها.
به عبارت دیگر ما با استفاده از Overriding متدها میتوانیم متد Print را برای کلاسهای فرزند طبق نیاز خود ویرایش کنیم!
برای اینکار ابتدا باید یک تغییر کوچک در متد نوشته شده داخل کلاس والد ایجاد کنیم:
public abstract class Person
{
public int Id { get; set; }
public string FullName { get; set; }
public Person(int id, string fullName)
{
this.StudentId = id;
this.FullName = fullName;
}
public Virtual void Print()
{
Console.WriteLine($"id: {Id}\tname: {FullName }");
}
}
همانطور که در کد بالا مشاهده میکنید، متد Print را بصورت Virtual تعریف نمودیم.
پس برای Overriding متدها، ابتدا متد داخل کلاس والد را بصورت Virtual تعریف میکنیم.
سپس به سراغ کلاسهای فرزند رفته و برای هرکدام از کلاسها، متد Print را دوباره نویسی میکنیم.
فقط قبل از اینکه وارد دوباره نویسی متد کلاس والد درون کلاسهای فرزند بشویم، به چند نکته توجه داشته باشید:
نکته ۱: حتما باید متد داخل کلاس والد، کلمه Virtual را داشته باشد.
نکته ۲: سطح دسترسی متد داخل کلاس فرزند باید با سطح دسترسی متد کلاس والد یکسان باشد.
نکته ۳: نوع خروجی متد داخل کلاس فرزند باید با نوع خروجی متد کلاس والد یکسان باشد.
نکته ۴: حتما باید متد کلاس فرزند، کلمه override را داشته باشد.
نکته ۵: نام متد داخل کلاس فرزند حتما باید با نام متد داخل کلاس والد یکسان باشد.
نکته ۶: محدوده بلاکها میتوانند کدهای یکسان نداشته باشند، که البته هدف از دوباره نویسی همین است!
حال که نکتهها را متوجه شدید، به سراغ دوباره نویسی متد Print در کلاسهای فرزند میرویم:
public class Student :Person
{
public int StudentCode { get; set; }
public Student(int studentCode, int id, string fullName):base(id, fullName)
{
this.StudentCode = studentCode;
}
public override void Print()
{
Console.WriteLine($"Code: {StudentCode}\tId: {Id}\tName: {FullName}");
}
}
public class Master :Person
{
public string MasterDegree { get; set; }
public Master(string masterDegree, int id, string fullName):base(id, fullName)
{
this.MasterDegree = masterDegree;
}
public override void Print()
{
Console.WriteLine($"Degree: {MasterDegree}\tId: {Id}\tName: {FullName}");
}
}
public class Employee :Person
{
public int EmployeeSalary { get; set; }
public Employee(int employeeSalary, int id, string fullName):base(id, fullName)
{
this.EmployeeSalary = employeeSalary;
}
public override void Print()
{
Console.WriteLine($"Salary: {EmployeeSalary}\tId: {Id}\tName: {FullName}");
}
}
همانطور که در سه قطعه کد بالا مشاهده مینمایید، متد Print از کلاس والد، برای هر سه کلاس فرزند دوباره نویسی یا همان override شد.
فقط توجه داشته باشید که ساختار متدهای override، دقیقا همان ساختار متد Virtual داخل کلاس والد باشد!
به همین علت در اینجا ما متدهای دوباره نویسی شده را با سطح دسترسی public، خروجی void و نام Print تعریف کردهایم.
با اینکار دیگر در زمان فراخوانی متد Print توسط اشیاء تعریف شده از کلاسهای فرزند، متد Print داخل کلاس والد یعنی Person فراخوانی نمیشود، بلکه هر نمونه تعریف شده از کلاسهای فرزند، متد Print داخل کلاس خود را فراخوانی خواهند کرد که به این شکل خروجیهای متفاوتی خواهند داشت.
جهت شرکت در دورههای زبان برنامه نویسی سیشارپ، از کد تخفیف heplc30 استفاده کنید.