بازنویسی متد در سی شارپ Method Overriding — به زبان ساده

تصویر شاخص بازنویسی متد در سی شارپ

در این مقاله، با مفهوم بازنویسی متد در سی شارپ «#Method Overriding in C» آشنا خواهیم شد و نحوه استفاده از کلیدواژه‌های مختلف مانند virtual و override برای بازنویسی متدها را بررسی می‌کنیم. همچنین به بررسی محدودیت‌ها و قوانینی که در این زمینه وجود دارند خواهیم پرداخت تا بهتر درک کنیم که چگونه می‌توانیم این قابلیت را در کدهای خود به طور مؤثر به کار ببریم.

مقدمه

در زبان برنامه‌نویسی سی شارپ #C، یکی از مفاهیم کلیدی که به توسعه‌دهندگان امکان می‌دهد کدهایی انعطاف‌پذیرتر و مقیاس‌پذیرتر بنویسند، بازنویسی متد «Method Overriding» است. این ویژگی از ویژگی‌های مهم چندریختی پویا «Dynamic Polymorphism» محسوب می‌شود که به کلاس‌های مشتق‌شده اجازه می‌دهد تا رفتارهای متدهای کلاس پایه را تغییر دهند. بازنویسی متد این امکان را فراهم می‌کند که یک متد در کلاس پایه تعریف شده، اما در کلاس مشتق‌شده پیاده‌سازی جدیدی داشته باشد. این ویژگی به برنامه‌نویسان این امکان را می‌دهد که کدهای خود را به گونه‌ای طراحی کنند که قابلیت استفاده مجدد و گسترش آسان‌تری داشته باشند.

بازنویسی متد در سی شارپ چیست؟

بازنویسی متد در سی شارپ مشابه تابع مجازی «Virtual Function» در سی پلاس‌پلاس ++C است. این تکنیک به ما امکان می‌دهد که توابع یک کلاس دیگر (کلاس پایه) را در کلاس مشتق شده فراخوانی کنیم. ایجاد یک متد در کلاس مشتق شده با همان امضا «Signature» مانند متد موجود در کلاس پایه، بازنویسی متد نامیده می‌شود.

به زبان ساده، بازنویسی قابلیتی است که به یک زیرکلاس «Subclass» یا کلاس فرزند اجازه می‌دهد یک پیاده‌سازی خاص از متدی را ارائه دهد که قبلاً در یکی از ابرکلاس‌ها «Super Classes» یا کلاس‌های والد تعریف شده است. هنگامی که یک متد در زیرکلاس دارای همان نام، همان پارامترها (یا امضا) و همان نوع بازگشتی (یا زیرنوع آن) مانند متدی در ابرکلاس باشد، گفته می‌شود که متد در زیرکلاس، متد موجود در ابرکلاس را بازنویسی «Override» کرده است.

بازنویسی متد در سی شارپ یکی از روش‌هایی است که چندریختی زمان اجرا «Run Time Polymorphism» یا چندریختی پویا «Dynamic Polymorphism» را در #C فراهم می‌کند.

متدی که توسط یک دستور override بازنویسی می‌شود، متد پایه‌ی بازنویسی‌شده «Overridden Base Method» نامیده می‌شود. یک متد override، پیاده‌سازی جدیدی از عضوی است که از یک کلاس پایه به ارث برده شده است. متد پایه‌ای که بازنویسی می‌شود باید مجازی «Virtual»، انتزاعی «Abstract» یا خودش بازنویسی‌شده «Override» باشد.

تصویری از مفهوم بازنویسی متد

مثال

class base_class
{
    public void PgS();
}

class derived_class : base_class
{
    public void PgS();
}

class Main_Method
{
 static void Main()
 {
    derived_class d = new derived_class();
    d.PgS();
 }
}

در مثال بالا، کلاس پایه در کلاس مشتق‌شده به ارث برده شده است و متد ()PgS که دارای همان امضا در هر دو کلاس است، بازنویسی «Override» شده است.

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

در زبان برنامه‌نویسی #C، می‌توانیم از ۳ نوع کلیدواژه برای بازنویسی متدها استفاده کنیم:

  •  virtual: برای تعریف متدهای قابل بازنویسی در کلاس پایه
  •  override: برای بازنویسی متدهای virtual یا abstract در کلاس مشتق‌شده
  •  base: برای دسترسی به اعضای کلاس پایه از داخل یک کلاس مشتق‌شده

کلیدواژه virtual در سی شارپ

تعدیل‌کننده «Modifier» یا کلیدواژه virtual در متد کلاس پایه استفاده می‌شود. این کلیدواژه برای تعدیل یک متد در کلاس پایه به‌کار می‌رود تا امکان بازنویسی آن متد در کلاس مشتق‌شده فراهم شود.

کلیدواژه override در سی شارپ

تعدیل‌کننده «Modifier» یا کلیدواژه override در متد کلاس مشتق‌شده استفاده می‌شود. این کلیدواژه برای تعدیل یک متد مجازی «Virtual» یا انتزاعی «Abstract» در کلاس مشتق‌شده استفاده می‌شود که در کلاس پایه تعریف شده است.

مثال:

class base_class
{
    public virtual void PgS();
}

class derived_class : base_class
{
    public override void PgS();
}
class Main_Method
{
 static void Main()
 {
    derived_class d = new derived_class();
    d.PgS();
    
      base_class b = new derived_class();
        b.PgS();
 }
}

در مثال بالا، ابتدا d به شیء کلاس derived_class اشاره می‌کند و متد ()PgS مربوط به کلاس derived_class را فراخوانی می‌کند. سپس، b به عنوان یک ارجاع از کلاس base استفاده می‌شود، اما شیء کلاس derived_class را در خود نگه می‌دارد و متد ()PgS مربوط به کلاس derived_class را فراخوانی می‌کند.

در مثال بالا، متد ()PgS برای بازنویسی متد در کلاس مشتق‌شده، از کلاس پایه اجازه می‌گیرد.

مثال ۱: بازنویسی متد در سی شارپ بدون استفاده از کلیدواژه‌های virtual و override

// C# program to demonstrate the method overriding 
// without using 'virtual' and 'override' modifiers
using System;

// base class name 'baseClass'
class baseClass

{
 public void show()
 {
  Console.WriteLine("Base class");
 }
}

// derived class name 'derived'
// 'baseClass' inherit here
class derived : baseClass
{
 
 // overriding
 new public void show() 
 {
  Console.WriteLine("Derived class");
 }
}

class PStore
{
 
 // Main Method
 public static void Main()
 {
  
  // 'obj' is the object of
  // class 'baseClass'
  baseClass obj = new baseClass();
  
  
  // invokes the method 'show()'
  // of class 'baseClass'
  obj.show();
  
  obj = new derived();
  
  // it will invokes the method 
  // 'show()' of class 'baseClass'
  obj.show();
  
 }
}

خروجی

Base class
Base class

توضیح: در این برنامه، شیء obj دو بار کلاس baseClass را فراخوانی کرده و متد ()show را از کلاس baseClass اجرا می‌کند. برای جلوگیری از این مشکل، از کلیدواژه‌های virtual و override استفاده می‌کنیم.

مثال ۲: بازنویسی متد در سی شارپ با استفاده از کلیدواژه‌های virtual و override

// C# program to illustrate the use of 
//'virtual' and 'override' modifiers
using System;

class baseClass {

 // show() is 'virtual' here
 public virtual void show()
 {
  Console.WriteLine("Base class");
 }
}


// class 'baseClass' inherit 
// class 'derived'
class derived : baseClass
{
 
 //'show()' is 'override' here
 public override void show()
 {
  Console.WriteLine("Derived class");
 }
}

class PStore
{
 
 // Main Method
 public static void Main()
 {
  
  baseClass obj;

  // 'obj' is the object
  // of class 'baseClass'
  obj = new baseClass();
  
  // it invokes 'show()' 
  // of class 'baseClass'
  obj.show();
  

  // the same object 'obj' is now
  // the object of class 'derived'
  obj = new derived();
  
  // it invokes 'show()' of class 'derived'
  // 'show()' of class 'derived' is overridden
  // for 'override' modifier
  obj.show();
  
 }
}

خروجی

Base class
Derived class

کلیدواژه base در سی شارپ

کلیدواژه base برای دسترسی به اعضای کلاس پایه از داخل کلاس مشتق‌شده استفاده می‌شود. این کلیدواژه عمدتاً برای دسترسی به سازنده‌ها «Constructors»، متدها «Methods» یا توابع کلاس پایه به کار می‌رود.

نکات مهم درباره کلیدواژه base

  • این کلیدواژه نمی‌تواند در داخل متدهای static استفاده شود.
  • base مشخص می‌کند که هنگام ایجاد یک نمونه از کلاس مشتق‌شده، کدام سازنده از کلاس پایه باید فراخوانی شود.

کاربردهای کلیدواژه base

  • فراخوانی متدها یا توابع کلاس پایه از کلاس مشتق‌شده.
  • فراخوانی داخلی سازنده کلاس پایه در زمان وراثت.

مثال ۳: بازنویسی متد در سی شارپ با استفاده از کلیدواژه base

// C# program to show the use of 'base' 
// keyword in method overriding
using System;

// base class
public class web {
 
 
 string name = "ProgramStore";

 // 'showdata()' is member method,
 // declare as virtual
 public virtual void showdata()
 {
  Console.WriteLine("Website Name: " + name);
 }
}
// derived class
// class 'web' is inherits
// class 'stream'
class stream : web
{
 string s = "Computer Science";
 
 //'showdata()' is overridden
 // in derived class
 public override void showdata()
 {
  // Calling 'showdata()' of base
  // class using 'base' keyword
  base.showdata();
  
  Console.WriteLine("About: " + s);
 }
}
class PStore
{
 // Main Method
 static void Main()
 {
  
  // 'E' is object of class stream
  // also works as object of 
  // class 'web'
  stream E = new stream();
  
  // it first invokes 'showdata()'
  // of class 'web' then it invokes 
  // 'showdata()' of class 'stream'
  E.showdata();
  
 }
}

خروجی

Website Name: ProgramStore
About: Computer Science

مثال ۴: نحوه استفاده از کلیدواژه base برای فراخوانی سازنده کلاس پایه از کلاس مشتق‌شده

// C# program to show how base keyword 
// specifies the calling of base-class
// constructor from the derived class
// when derived class instances are created
using System;

// base class
public class clssA {
 
 int n1, n2;

 // default constructor
 public clssA()
 {
  Console.WriteLine("Default Constructor Invoked");
 }

 // parameterized constructor
 public clssA(int i, int j)
 {
  
  // construct values
  n1 = i;
  n2 = j;
  Console.WriteLine("Parameterized Constructor Invoked");
  Console.WriteLine("Invoked Values are: " + n1 + " and " + n2);
 }
}

// derived class
public class DerivedClass : clssA
{
 
 // This constructor will instantiate
 // 'clssA()' [no argument constructor]
 // using 'base' keyword
 public DerivedClass() : base() { }


 // This constructor will instantiate
 // 'clssA(int i, int j)' [parameterized
 // constructor] using 'base' keyword
 public DerivedClass(int i, int j) : base(i, j) { }

// Main Method
static void Main()
{
 
 // invoke no argument constructor
 DerivedClass d1 = new DerivedClass();
 
 Console.WriteLine();

 // invoke parameterized constructor
 DerivedClass d2 = new DerivedClass(10, 20);
 
}
}

خروجی

Default Constructor Invoked

Parameterized Constructor Invoked
Invoked Values are: 10 and 20

هنگامی که یک نمونه «Instance» از کلاس مشتق‌شده ایجاد می‌شود، می‌توان با استفاده از کلیدواژه base مشخص کرد که کدام سازنده از کلاس پایه باید فراخوانی شود.

در مثال بالا، هنگام ایجاد شیء از کلاس مشتق‌شده، سازنده کلاس پایه به‌طور خودکار توسط base اجرا می‌شود.

مثال ۵: استفاده از کلیدواژه base برای فراخوانی سازنده کلاس پایه و متد آن از کلاس مشتق‌شده

در مثال زیر، هنگام ایجاد شیء از کلاس مشتق‌شده، هم سازنده کلاس پایه و هم متد آن توسط کلیدواژه base فراخوانی می‌شوند.

// C# program to show how 'base' keyword specifies
// the base-class constructor that called from 
// derived class and also calling a method 'swap' 
// from derived class using base keyword
using System;

// base class
public class clssA {
 
 public int n1, n2;

 // default constructor
 public clssA()
 {
  Console.WriteLine("In clssA 'no argument constructor' invoked");
 }

 // parameterized constructor
 public clssA(int i, int j)
 {
  
  // construct values
  n1 = i;
  n2 = j;
  Console.WriteLine("in clssA 'parameterized constructor' invoked");
  Console.WriteLine("the invoked values are " + n1 + " and " + n2);
  Console.WriteLine();
 }

 public virtual void swap()
 {
  Console.WriteLine("swap function of base class(clssA) invoked");
  Console.WriteLine("Before swap num1 = {0} and num2 = {1}", n1, n2);

  // swapping
  int t = n1;
  n1 = n2;
  n2 = t;
  Console.WriteLine("After swap num1 = {0} and num2 = {1}", n1, n2);
 }
}

// derived class
public class DerivedClass : clssA {
 
 // This constructor will instantiate
 // 'clssA' [no argument constructor]
 // using 'base' keyword
 public DerivedClass() : base() { }

 // This constructor will instantiate 
 // 'clssA' [parameterized constructor]
 // using 'base' keyword
 public DerivedClass(int i, int j) : base(i, j) { }

 public override void swap()
 {
  
  // it access the swap function of
  // 'clssA' using 'base' keyword
  base.swap();
  
  Console.WriteLine();

  Console.WriteLine("Swap function of derived class invoked");
  Console.WriteLine("Before swap num1 = {0} and num2 = {1}", n1, n2);

  // swapping
  int t = n1;
  n1 = n2;
  n2 = t;
  Console.WriteLine("After swap num1 = {0} and num2 = {1}", n1, n2);
 }

// Main Method
static void Main()
{
 
 // invoke no argument constructor
 DerivedClass d1 = new DerivedClass();
 
 Console.WriteLine();

 // invoke parameterized constructor
 DerivedClass d2 = new DerivedClass(10, 20);
 
 // calling swap function
 d2.swap();
 
}
}

خروجی

In clssA 'no argument constructor' invoked

in clssA 'parameterized constructor' invoked
the invoked values are 10 and 20

swap function of base class(clssA) invoked
Before swap num1 = 10 and num2 = 20
After swap num1 = 20 and num2 = 10

Swap function of derived class invoked
Before swap num1 = 20 and num2 = 10
After swap num1 = 10 and num2 = 20

نکته: بازنویسی متد در سی شارپ تنها در کلاس‌های مشتق‌شده امکان‌پذیر است. زیرا متد در کلاس مشتق‌شده از کلاس پایه بازنویسی می‌شود. یعنی متد در کلاس پایه تعریف شده و در کلاس مشتق‌شده بازنویسی می‌شود.

یک متد غیر مجازی «non-virtual» یا متد استاتیک «static» نمی‌تواند بازنویسی شود. متدهایی که مجازی «virtual» نیستند یا استاتیک «static» هستند، به‌طور مستقیم نمی‌توانند توسط کلاس‌های مشتق‌شده بازنویسی شوند.

متد override و متد virtual باید دارای یکسان‌ترین سطح دسترسی «access level modifier» باشند.

این یعنی اگر متد virtual در کلاس پایه دارای دسترسی public باشد، متد override در کلاس مشتق‌شده نیز باید دسترسی public داشته باشد.

جمع بندی

در این مقاله، مفهوم بازنویسی متد در سی شارپ #C را مورد بررسی قرار دادیم و نشان دادیم که چگونه این ویژگی به توسعه‌دهندگان این امکان را می‌دهد که متدهای کلاس‌های پایه را در کلاس‌های مشتق‌شده بازنویسی کنند و رفتار آن‌ها را تغییر دهند. با استفاده از کلیدواژه‌های virtual و override، می‌توانیم کدهایی انعطاف‌پذیر و مقیاس‌پذیر ایجاد کنیم که به راحتی قابل گسترش و نگهداری باشند.

همچنین به محدودیت‌ها و قوانینی مانند نیاز به داشتن یکسان بودن سطح دسترسی بین متد virtual و متد override و این که متدهای غیر مجازی یا استاتیک نمی‌توانند بازنویسی شوند، اشاره کردیم. این قوانین به ما کمک می‌کنند تا از بروز اشتباهات جلوگیری کرده و استفاده بهینه از این ویژگی را داشته باشیم.

در نهایت، بازنویسی متد در سی شارپ یکی از ابزارهای قدرتمند برای پیاده‌سازی چندریختی پویا (Dynamic Polymorphism) است که در طراحی سیستم‌های پیچیده و انعطاف‌پذیر نقش مهمی ایفا می‌کند. استفاده صحیح از این ویژگی می‌تواند به برنامه‌نویسان کمک کند تا کدهایی قابل فهم، قابل نگهداری و مقیاس‌پذیر بنویسند.

میزان رضایتمندی
لطفاً میزان رضایت خودتان را از این مطلب با دادن امتیاز اعلام کنید.
[ امتیاز میانگین 5 از 3 نفر ]
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.

دیدگاه‌ خود را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

5 × 1 =



برچسب‌ها:
سی شارپ


پیمایش به بالا