محتویات سایت
        برچسب های محبوب 








 
   فراخوانی یک متد مجازی در سازنده ی یک کلاس
  در این ترفند به بررسی یک نکته بسیار مهم، هنگام فراخوانی توابع و اعضای مجازی (virtual) در سازنده ی یک کلاس می پردازم.
   C#
   ۱۶۹۶۲
   دریافت فایل ضمیمه
   مرتضی صحراگرد
   ۱۳۸۸/۶/۲۷
نسخه قابل چاپ نسخه قابل چاپ

مقدمه:

یکی از روش های معمول در برنامه نویسی، فراخوانی توابع در سازنده (Constructor) کلاس می باشد. توابعی که در سازنده ی یک کلاس فراخوانی می شوند، در حقیقت هنگامی که یک آبجکت از نوع این کلاس ساخته می شود، آن ها فراخوانی می گردند. این عمل در حالت عادی هیچگونه مشکلی ندارد ولی اگر این متد از نوع مجازی (virtual) باشد یعنی قابلیت override شدن داشته باشد، این عمل بسیار خطرناک می باشد.

ادامه این ترفند را با بررسی یک مثال ادامه می دهیم.

شروع :

در قسمت زیر دو کلاس را مشاهده می نمایید.

نام کلاس اول Parent بوده و دارای یک متد مجازی به نام Method می باشد. این کلاس در سازنده خود این متد را فراخوانی نموده است.

نام کلاس دوم Child بوده و از کلاس Parent به ارث رفته است. این کلاس تابع Method که متعلق به کلاس Parent می باشد را override نموده است.

public class Parent

{

    public Parent()

    {

        Console.WriteLine("--- Here is Parent class constructor");

        Method();

    }

 

    public virtual void Method()

    {

        Console.WriteLine("--- Here is Parent Method");

    }

}

 

public class Child:Parent

{

    public Child()

    {

        Console.WriteLine("--- Here is Child class constructor");

    }

 

    public override void Method()

    {

        Console.WriteLine("--- Here is Child Method");

    }

}

اکنون ما یک آبجکت از نوع کلاس Child ایجاد می کنیم.

class Program

{

    static void Main(string[] args)

    {

        Child child = new Child();

        Console.ReadKey();

    }

}

برنامه را اجرا نموده و نتیجه زیر را ملاحظه می نماییم.

 

خوب، به عقیده شما چه مشکلی در شکل بالا نمایان است؟!

اتفاق بسیار خطرناکی رخ داده است. با توجه به اینکه کلاس Child از کلاس Parent به ارث رفته است پس قبل از اینکه سازنده Child فراخوانی شود، ابتدا سازنده کلاس Parent فراخوانی می شود.

سازنده کلاس Parent در درون خود، تابع  Method خود را فراخوانی نموده است. ولی چون این متد توسط کلاس Child در حقیقت override شده است، در نتیجه به جای اینکه تابع کلاس Parent فراخوانی شود، تابع کلاس Child فراخوانی شده است.

یعنی سازنده کلاس Parent ، متد مربوط به کلاس Child را فراخوانی نموده است که معمولا این عمل مورد انتظار ما نیست!

دومین نکته ای که از شکل بالا نتیجه می شود، این است که متد مربوط به کلاس Child زمانی فراخوانی شده است که هنوز این کلاس ساخته نشده است. یعنی هنوز سازنده کلاس Child فراخوانی نشده است. در نتیجه اگر در داخل متد کلاس Child از اعضایی استفاده کرده باشیم که عمل Initialization آن ها قرار بوده در سازنده کلاس انجام شود، با یک خطایی مشابه زیر مواجه می شویم.

Object reference not set to an instance of an object

نکته :

این موضوع در مورد اعضای (Property های) مجازی کلاس نیز صدق می کند.

هنگام فراخوانی توابع مجازی در سازنده کلاس، متاسفانه کامپایلر هیچ هشداری در این رابطه نمی دهد و بنابراین به خاطر سپردن این ترفند بسیار ضروری می باشد.

قطعه کد کامل این ترفند از لینک بالای صفحه قابل در یافت می باشد.