کانال بله, جهت پشتیبانی و اطلاع رسانی کانال بله, جهت پشتیبانی و اطلاع رسانی
عضویت

کلاس های تو در تو (nested class) در سی شارپ

وقتی داری C# یاد می‌گیری، خیلی زود با کلاس‌ها و نحوه ارتباطشون با بخش‌های مختلف برنامه روبه‌رو می‌شی. یکی از موضوعاتی که ممکنه در این مسیر برات سؤال بشه، اینه که آیا می‌شه یک کلاس رو داخل کلاس دیگه قرار داد یا نه. این کار در بعضی شرایط می‌تونه به مرتب‌تر شدن کد و محدود کردن محدوده دسترسی کمک کنه.

توی این مقاله با مفهوم کلاس‌های تودرتو (Nested Classes) در C# آشنا می‌شیم و می‌بینیم کلاس‌های درونی و بیرونی چطور می‌تونن به اعضای هم دسترسی داشته باشن. بعد هم با چند مثال کدنویسی، نحوه استفاده از کلاس تودرتو و همین‌طور استفاده از یک کلاس به عنوان فیلد رو بررسی می‌کنیم.

گاهی لازمه یک کلاس رو داخل کلاس دیگه تعریف کنیم. یکی از مهم‌ترین دلایل این کار، محدود کردن محدوده تعریف و دسترسی به اعضای کلاس داخلیه. در C# این امکان وجود داره و روش‌های مختلفی هم برای کنترل دسترسی کلاس بیرونی و درونی به اعضای یکدیگر داریم. توی این بخش از آموزش C# می‌خوایم این موضوع رو بررسی کنیم.

می‌تونیم یک کلاس رو داخل کلاس دیگه قرار بدیم. به کلاسی که داخل کلاس دیگری ایجاد می‌شه، کلاس nested یا تودرتو می‌گن. برای انجام این کار، داخل کلاس موجود کلیک کن و کد مربوط به کلاس جدید رو وارد کن. اول کلیدواژه‌ی class، بعد اسم کلاس و کاراکترهای {} رو بنویس. حالا کل کلاس رو انتخاب کن، روی اون راست‌کلیک کن و گزینه‌ی Surround With... رو انتخاب کن. در لیستی که باز می‌شه، روی class دوبار کلیک کن. در مثال زیر، کلاسی به نام Inside داخل کلاس دیگری به نام Outside قرار گرفته:

                 
public class Outside 
‎{‎ 
    public class Inside 
‎    { 
    }‎ 
‎} 

با همین روش می‌تونی هر تعداد کلاس که لازم داری داخل کلاس‌های دیگه قرار بدی. مدیریت و کنترل یک کلاس تودرتو هم تفاوت خاصی با یک کلاس معمولی نداره. مثلاً می‌تونی فیلدها، متدها و properties موردنیازت رو داخل کلاس تودرتو یا کلاس بیرونی تعریف کنی.
اما یک نکته مهم اینجاست: صرفاً اینکه یک کلاس رو داخل کلاس دیگه قرار بدی، باعث نمی‌شه یک ارتباط برنامه‌ای خاص بین این دو کلاس ایجاد بشه. یعنی کلاس تودرتو (nested class یا کلاس درونی) فقط به خاطر اینکه داخل کلاس بیرونی قرار گرفته، به صورت خودکار به اعضای اون دسترسی پیدا نمی‌کنه. در واقع این دو کلاس از هم جدا هستن.
اسم کلاس تودرتو خارج از کلاس بیرونی هم قابل مشاهده نیست. برای استفاده از کلاس تودرتو در خارج از کلاس بیرونی، باید نام کامل اون رو در جایی که می‌خوای ازش استفاده کنی مشخص کنی. مثلاً اگر بخوای متغیری از نوع Inside رو در بخشی از برنامه و خارج از Outside تعریف کنی، باید نام کلاس رو به شکل مناسب مشخص کنی.

مثال:

                 
using System;‎ 
 
public class Outside 
{‎ 
    public class Inside 
    {‎ 
        public Inside()‎ 
        ‎{‎ 
        ‎    Console.WriteLine(" -= Inside =-");‎ 
        ‎}‎ 
    }‎ 
 
‎    public Outside()‎ 
‎    {‎ 
        Console.WriteLine(" =- Outside -=");‎ 
    }‎ 
}‎ 
 
public class Exercise 
{‎ 
    static int Main()‎ 
    {‎ 
        Outside recto = new Outside();‎ 
        Outside.Inside ins = new Outside.Inside();‎ 
 
        return 0;‎ 
    }‎ 
‎} 

نتیجه

 
=- Outside -=‎ 
‎ -= Inside =- 

چون بین کلاس درونی و کلاس بیرونی (دربرگیرنده) به خودی خود ارتباط خاصی وجود نداره، برای اینکه کلاس بیرونی بتونه به کلاس درونی دسترسی داشته باشه، باید از اعضای ایستا (static members) اون استفاده کنیم. یعنی هر عضوی از کلاس درونی که قراره از داخل کلاس بیرونی بهش دسترسی داشته باشیم، می‌تونه به صورت static تعریف بشه. به مثال زیر توجه کن.

                 
using System;‎ 
 
public class Outside 
‎{‎ 
    public class Inside 
    {‎ 
        public static string InMessage;‎ 
        public Inside()‎ 
        ‎{‎ 
            Console.WriteLine(" -= Insider =-");‎ 
            inMessage = "Sitting inside while it's raining";‎ 
        ‎}‎ 
         
        public static void Show()‎ 
        ‎{‎ 
            Console.WriteLine("Show me the wonderful world of C# ‎Programming");‎ 
        ‎}‎ 
    }‎ 
 
    public Outside()‎ 
    {‎ 
        Console.WriteLine(" =- The Parent -=");‎ 
    }‎ 
     
    public void Display()‎ 
    {‎ 
        Console.WriteLine(Inside.InMessage);‎ 
        Inside.Show();‎ 
    }‎ 
}‎ 
 
class Exercise 
‎{‎ 
    static int Main()‎ 
    ‎{‎ 
        Outside recto = new Outside();‎ 
        Outside.Inside ins = new Outside.Inside();‎ 
        Recto.Display();‎ 
‎ 
        return 0;‎ 
    }‎ 
‎} 

به همین شکل، اگر بخوای از داخل کلاس درونی به کلاس بیرونی دسترسی داشته باشی، می‌تونی از اعضای ایستا کلاس بیرونی استفاده کنی. یعنی اعضایی از کلاس بیرونی که قرار هست از داخل کلاس درونی بهشون دسترسی داشته باشی، باید به صورت static تعریف بشن.

مثال:

                 
using System;‎ 
 
public class Outside 
‎{‎ 
    public class Inside 
    ‎{‎ 
        public static string InMessage;‎ 
        public Inside()‎ 
        {‎ 
            Console.WriteLine(" -= Insider =-");‎ 
            InMessage = "Sitting inside while it's raining";‎ 
        ‎}‎ 
     
        public static void Show()‎ 
        {‎ 
            Console.WriteLine("Show me the wonderful world of C# ‎Programming");‎ 
        ‎}‎ 
     
        public void FieldFromOutside()‎ 
        {‎ 
            Console.WriteLine(Outside.OutMessage);‎ 
        ‎} 
    ‎}‎ 
 
    private static string OutMessage;‎ 
     
    public Outside()‎ 
    ‎{‎ 
        Console.WriteLine(" =- The Parent -=");‎ 
        OutMessage = "Standing outside! It's cold and raining!!";‎ 
    ‎}‎ 
     
    public void Display()‎ 
    ‎{‎ 
        Console.WriteLine(Inside.InMessage);‎ 
        Inside.Show();‎ 
    }‎ 
‎}‎ 
 
public class Exercise 
‎{‎ 
    static int Main()‎ 
    {‎ 
        Outside recto = new Outside();‎ 
        Outside.Inside Ins = new Outside.Inside();‎ 
        ‎Recto.Display();‎ 
        Console.WriteLine();‎ 
        Ins.FieldFromOutside();‎ 
 
        return 0;‎ 
    }‎ 
‎} 

نتیجه

 
 =- The Parent -=‎ 
  ‎-= Insider =-‎ 
Sitting inside while it's raining 
Show me the wonderful world of C# Programming 
Standing outside! It's cold and raining!! 

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

مثال:

                 
using System;‎ 
 
public class Outside 
‎{‎ 
    ‎// A member of the nesting class‎ 
    private string OutMessage;‎ 
     
    // The nested class‎ 
    public class Inside 
    ‎{‎ 
        ‎// A field in the nested class‎ 
        public string InMessage;‎ 
        ‎‎ 
        // A constructor of the nested class‎ 
        public Inside()‎ 
        ‎{‎ 
            Console.WriteLine(" -= Insider =-");‎ 
            this.InMessage = "Sitting inside while it's raining";‎ 
        ‎}‎ 
        ‎ 
        ‎// A method of the nested class‎ 
        ‎public void Show()‎ 
        ‎{‎ 
            ‎// Declare a variable to access the nesting class‎ 
            Outside outsider = new Outside();‎ 
            Console.WriteLine(outsider.OutMessage);‎ 
        ‎}‎ 
    } // End of the nested class‎ 
 
    ‎// A constructor of the nesting class‎ 
    public Outside()‎ 
    ‎{‎ 
        this.OutMessage = "Standing outside! It's cold and raining!!";‎ 
        Console.WriteLine(" =- The Parent -=");‎ 
    ‎}‎ 
     
    ‎// A method of the nesting class‎ 
    ‎public void Display()‎ 
    ‎{‎ 
        Console.WriteLine(insider.InMessage);‎ 
    ‎}‎ 
     
    ‎// Declare a variable to access the nested class‎ 
    Inside insider = new Inside();‎ 
‎}‎ 
 
public class Exercise 
‎{ 
    static int Main()‎ 
    {‎ 
        Outside recto = new Outside();‎ 
        Outside.Inside Ins = new Outside.Inside();‎ 
        Ins.Show();‎ 
        Recto.Display();‎ 
 ‎ 
        return 0;‎ 
    ‎} 
‎} 

نتیجه

 
-= Insider =-‎ 
‎=- The Parent -=‎ 
-= Insider =-‎ 
-= Insider =-‎ 
=- The Parent -=‎ 
Standing outside! It's cold and raining!!‎ 
Sitting inside while it's raining 

کلاسی به عنوان فیلد

درست مثل متغیرهایی که تا اینجا استفاده کردیم، می‌تونیم یک کلاس یا ساختار رو هم به عنوان متغیر عضو یک کلاس دیگه تعریف کنیم. برای اینکه بتونی یک کلاس دیگه رو داخل کلاس خودت استفاده کنی، اول باید اون کلاس در دسترست باشه. این کلاس می‌تونه یکی از کلاس‌های آماده C# باشه یا خودت اون رو ایجاد کرده باشی.

مثال:

                 
public class Point 
‎{‎ 
‎    internal short x;‎ 
‎    internal short y;‎ 
} 

فیلد در واقع یک متغیر عضو کلاسه که به جای یک نوع اولیه (primitive type)، از یک کلاس دیگه ساخته می‌شه. برای اینکه یک کلاس رو به عنوان متغیر عضو کلاس دیگه استفاده کنی، کافیه متغیر مربوط به اون رو تعریف کنی. مثال زیر رو ببین:

                 
public class Point 
‎{‎ 
‎    internal short x;‎ 
‎    internal short y;‎ 
}‎ 
 
public class CoordinateSystem 
‎{‎ 
    public Point start;‎ 
‎} 

بعد از اینکه یک کلاس رو به عنوان عضو یک کلاس دیگه تعریف کردی، می‌تونی مثل بقیه متغیرها از اون استفاده کنی. اما چون این عضو از نوع کلاس و در واقع یک reference هست، موقع استفاده باید چند نکته رو در نظر داشته باشی.
بعد از تعریف متغیر عضو، باید مطمئن بشی که حافظه‌ی لازم برای اون تخصیص داده شده. همچنین باید متغیر به شکل درست و مناسب مقداردهی (اولیه) شده باشه. اگر این موارد رعایت نشن، موقع ترجمه یا compile برنامه با error مواجه می‌شی.

اگه می‌خوای این مفاهیم رو در کنار سایر مباحث پایه و کاربردی C# منظم‌تر یاد بگیری، دوره آموزش C# می‌تونه قدم بعدی خوبی توی مسیر یادگیریت باشه. وقتی مفاهیم زبان رو اصولی یاد بگیری، موضوعاتی مثل کلاس‌ها، اعضای کلاس و ساختار برنامه هم خیلی راحت‌تر برات قابل درک و استفاده می‌شن.

1405/06/11 15443 5924
رمز عبور : tahlildadeh.com یا www.tahlildadeh.com
نظرات شما

نظرات خود را ثبت کنید...