مفهوم برنامه نویسی شی گرا و کلاس در سی شارپ

بدون شک مبحث کلاس ها، مهمترین و پرکاربردترین مبحث نه تنها در سی شارپ بلکه در تمامی زبان های برنامه نویسی شی گرا می باشد. مبحث کلاس ها بسیار گسترده بوده و تسلط بر این مباحث باعث افزایش قدرت برنامه نویسی در پیاده سازی پروژه های متوسط و بزرگ می شود.

تعاریف اولیه

شناخت عناصر مورد استفاده در یک کلاس ضروری ترین امر برای ورود به دنیای برنامه نویسی شی گرا می باشد. در این بخش به معرفی آنها پرداخته و در مقالات بعدی به تفصیل راجع به هریک صحبت خواهیم کرد.

Class

واژه کلاس نشأت گرفته از classify یا classification بوده و به معنی دسته بندی می باشد. به عبارتی دیگر، به مجموعه ای از عناصر که دارای ویژگی ها (خصوصیات) و رفتار یکسان می باشند، کلاس گفته می شود.

توجه داشته باشید کلاس تنها یک تعریف می باشد همانند نقشه یک ساختمان که در آن مشخص می شود چه عناصری و به چه شکلی وجود داشته باشند.

Object

به نمونه ساخته شده از یک کلاس، object (شی) گفته می شود. در اصل کلاس همانند نقشه یک ساختمان و شی مشابه یک نمونه واقعی ساخته شده از روی آن نقشه می باشد. مهمترین تفاوت کلاس و شی آن است که هنگام تعریف شی از یک کلاس، به آن حافظه اختصاص داده می شود.

Method

در زبان های برنامه نویسی ساخت یافته تعریفی به نام function (تابع) وجود دارد. function به مجموعه دستوراتی گفته می شود که کار مشخصی را انجام می دهد. در زبان های برنامه نویسی شی گرا، به توابعی که داخل کلاس تعریف می شوند، متد گفته می شود.

Field

در دروس قبل با نحوه تعریف و استفاده از متغیرها در سی شارپ آشنا شدید. در زبان های برنامه نویسی شی گرا، به متغیرهایی که درون یک کلاس تعریف می شوند، فیلد گفته می شود.

Property

property در اصل تکمیل کننده ویژگی ها یک فیلد می باشد و حتی برخی از افراد برای آنها تعریف یکسانی ارائه می کنند. مهمترین هدف property، اعمال محدودیت دسترسی، اعتبار سنجی و کنترل اطلاعاتی می باشد که در برنامه مورد استفاده قرار می گیرند.

ایجاد کلاس

برای ایجاد یک کلاس مراحل زیر را دنبال کنید.

روی نام پروژه کلیک راست کرده و از منوی Add گزینه Class را انتخاب کنید.

ایجاد کلاس- سی شارپ

در کادر Name، نام کلاس را Student قرار داده و روی دکمه Add کلیک کنید.

تعیین نام کلاس-سی شارپ

بدین ترتیب کلاس مورد نظر به پروژه اضافه شده و کدهای آن نیز نمایش داده می شود. پسوند کلاس ها در سی شارپ cs. می باشد.

کلاس-سی شارپ

افزودن فیلد

منظور از فیلد ویژگی ها (مشخصات) یک عنصر می باشد. برای مثال عنصری مانند دانشجو فیلدهایی زیر متصور است:

  • کد دانشجویی
  • نام
  • نام خانوادگی
  • رشته تحصیلی

دقت داشته باشید که منظور از فیلد همان متغیری می باشد که درون کلاس تعریف می شود و هنگام تعریف فیلد می بایست type آن متناسب با اطلاعاتی باشد که قرار است درون آن قرار بگیرد.

class Student
{
    int id;
    string firstName, lastName, major;
}

افزودن متد

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

AccessLevel  ReturnValue  MethodName(Parameters)
{
	statements;
}

برای سطح دسترسی یکی از حالت های زیر را می توان انتخاب نمود.

  • private: متدهای private (خصوصی) تنها داخل خود کلاس قابل استفاده خواهند بود.
  • public: هنگامی که یک متد public تعریف می شود، هم توسط اعضای کلاس و هم خارج از کلاس قابل استفاده خواهد بود.
  • protected: توسط اعضای کلاس و کلاس هایی که از این کلاس ارث بری دارند قابل استفاده خواهد بود.

نوع بازگشتی

در صورتی که قصد داشته باشید متد مورد نظر پس از انجام عملیات، مقداری به برنامه برگشت دهد، می بایست نوع مقدار برگشتی که همانند type های مربوط به متغیرها (int, string, …) می باشند را تعیین نمایید. اگر قصد تعریف متدی بدون مقدار بازگشتی دارید می بایست نوع بازگشتی را void تعیین نمایید.

نکته: اگر متد تعیین شده مقدار بازگشتی داشت، در بدنه متد باید از دستور return استفاده کرد.

پارامترهای ورودی

تعیین پارامترهای ورودی اختیاری بوده و می توان متدی بدون پارامتر نیز تعریف کرد اما اگر قصد تعریف پارامتر داشته باشید می بایست به ازای هر پارامتر نوع آن نیز تعریف گردد.

چند نمونه از تعریف متدها

public void M1()
{

}

متدی به نام M1 که از نوع public می باشد. پارامتی ورودی ندارد و مقداری را نیز برگشت نمی دهد.

private void M2(int a)
{

}

متدی به نام M2 که از نوع private می باشد. یک عدد را به عنوان پارامتر دریافت کرده اما مقدار بازگشتی ندارد.

public int M3()
{

}

متدی به نام M3 که از نوع public می باشد. پارامتر ورودی ندارد اما خروجی آن از نوع int می باشد.

public int M4(string a, string b)
{

}

متدی به نام M4 که از نوع public می باشد. دو پارامتر از نوع string دریافت کرده و خروجی آن از نوع int می باشد.

مثال: متدی به نام ShowInfo به کلاس Student اضافه کنید که وظیفه آن نمایش اطلاعات دانشجو باشد.

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

class Student
{
    int id;
    string firstName, lastName, major;

    public void ShowInfo()
    {
        Console.WriteLine(id + " " + firstName + " " + lastName + " " + major);
    }
}

نحوه استفاده از کلاس

در اولین مقاله آموزشی سی شارپ توضیح داده شد که در برنامه هایی از نوع کنسول، کلاسی به نام Program وجود دارد که در این کلاس، متدی به نام Main تعریف شده است که متد آغازین برنامه بوده و اجرای برنامه از این متد شروع می شود. برای استفاده از کلاس Student ابتدا باید در متد Main مربوط به Program.cs یک نمونه (شی) از آن ایجاد کنیم.

ساختار کلی ساخت شی به شکل زیر است:

ClassName objectName = new ClassName();

بنابراین نمونه ساخته از کلاس Student به شکل زیر خواهد بود.

static void Main(string[] args)
{
    Student student1 = new Student();
}

توسط شی ساخته شده می توان به اعضای کلاس (فیلدها و متدها) دسترسی داشت. بنابراین مقدار دهی فیلدهای به شکل زیر خواهد بود.

student1.firstName = "Beno";

اما اگر قصد داشته باشید کدهای فوق را در متد Main بنویسید با خطا مواجه خواهید شد.

هنگامی که در متن خطا پیغام ...is in accessible را مشاهده میکنید علت این است که دسترسی به عنصر مورد نظر امکان پذیر نمی باشد. علت این امر آن است که چون هنگام تعریف فیلدها، سطح دسترسی آن تعیین نشده است، بصورت پیش فرض private در نظر گرفته می شود و همانطور که پیش تر توضیح داده شد، اعضای private تنها در خود کلاس قابل استفاده می باشند. برای رفع این خطا به کلاس Student مراجعه کرده و سطح دسترسی آنها را public کرده و تغییرات را ذخیره کنید.

public int id;
public string firstName, lastName, major;

حال می توانید به راحتی به عناصر کلاس Student دسترسی داشته و آنها را مقدار دهی کنید.

student1.id = 101;
student1.firstName = "Beno";
student1.lastName = "Academy";
student1.major = "Software";

پس از مقداردهی فیلدها می توانید متد مورد نظر را توسط شی ساخته شده فراخوانی کنید.

student1.ShowInfo();

بنابراین کد کامل برنامه به شکل زیر خواهد بود.

static void Main(string[] args)
{
    Student student1 = new Student();
    student1.id = 101;
    student1.firstName = "Beno";
    student1.lastName = "Academy";
    student1.major = "Software";
    student1.ShowInfo();
    Console.ReadLine();
}

پس ذخیره سازی و اجرا مشاهده خواهید کرد که مشخصات تعیین شده، نمایش داده می شود.

نمایش اطلاعات-کلاس-سی شارپ

Property

یکی از نکات بسیار مهم در طراحی کلاس ها، صحت اطلاعات ورودی می باشد و برای این امر استفاده از Property ها کمک شایانی به مدیریت اطلاعات ورودی می کند. فرض کنید قصد دارید برنامه ای برای نمایش زمان ایجاد نمایید که هر یک از آیتم ها (ساعت، دقیقه و ثانیه) را از کاربر دریافت کرده و سپس زمان وارد شده را بصورت کامل نمایش دهد.

اگر در این مثال کاربر برای ساعت عددی مانند 25 وارد نماید، تکلیف چیست؟

Property ها به برنامه نویس این قابلیت را می دهند که قبل از ذخیره سازی اطلاعات درون فیلد، آنها را بررسی کرده و در صورت درست بودن مقدار ورودی، آنها را در فیلد قرار دهند.

نحوه استفاده

هنگامی که در یک برنامه تعدادی فیلد تعیین می شود، بهتر است به ازای هریک از آنها Property مورد نظر نیز تعیین گردد. ساختار یک Property به شکل زیر است:

public type PropertyName{
	set{fieldname=value;}
	get{fieldname;}
}

هر Property از دو بخش get و set تشکیل شده است که بخش set وظیفه ذخیره سازی مقدار تعیین شده برای Property را در فیلد مربوطه بر عهده دارد و بخش get وظیفه استخراج اطلاعات ذخیره شده در فیلد و برگرداندن آن به برنامه.

هنگامی که برای فیلدها، Property متناظر تعریف می کنیم دیگر نیازی به public کردن فیلدها نیست. بنابراین فیلدها بصورت private تعریف شده و به ازای هر فیلد یک Property از نوع public مشخص می کنیم.

اعتبار سنجی اطلاعات

همانطور که گفته شد مهمترین وظیفه Property ها بررسی صحت اطلاعات قبل از ذخیره سازی می باشد. صحت اطلاعات ورودی در بخش set انجام می شود.

int hour;
public int Hour
{
    set
    {
        if(value >= 0 && value < 24)
        {
            hour = value;
        }
        else
        {
            hour = 0;
        }
    }
    get { return hour; }
}

نام Property تعیین شده بهتر است همان نام فیلد باشد با این تفاوت که حرف اول آن با حرف بزرگ نوشته شده  باشد و type مربوط به Property نیز می بایست دقیقاً مشابه فیلد مربوطه باشد.

مثال: کلاسی به نام Time تعریف کنید که حاوی سه فیلد برای دریافت ساعت، دقیقه و ثانیه باشد. همچنین متدی به نام ShowTime درون آن تعریف کنید که با فراخوانی آن، زمان کامل را نمایش دهد.

کدهای کلاس :Time

class Time
{
    int hour,minute,second;
    public int Hour
    {
        set
        {
            if (value >= 0 && value < 24)
            {
                hour = value;
            }
            else
            {
                hour = 0;
            }
        }
        get { return hour; }
    }
    public int Minute
    {
        set
        {
            if (value >= 0 && value < 60)
            {
                minute = value;
            }
            else
            {
                minute = 0;
            }
        }
        get { return minute; }
    }
    public int Second
    {
        set
        {
            if (value >= 0 && value < 60)
            {
                second = value;
            }
            else
            {
                second = 0;
            }
        }
        get { return second; }
    }

    public void ShowTime()
    {
        Console.WriteLine(Hour + ":" + Minute + ":" + Second);
    }
}

در این مثال برای هر فیلد یک Property مشخص شده است. در صورتی که کاربر برای ساعت عددی خارج از محدوده 0 تا 24 وارد نماید، به جای مقدار وارد شده، عدد 0 درون فیلد ذخیره می شود. همچنین در متد ShowTime نیز به جای نام فیلد، از Property متناظر استفاده شده است.

کدهای برنامه متد Main:

class Program
{
    static void Main(string[] args)
    {
        Time t = new Time();
        t.Hour = 14;
        t.Minute = 16;
        t.Second = 38;
        t.ShowTime();
        Console.ReadLine();
    }
}

در متد Main نیز دیگر دسترسی به فیلدها امکان پذیر نیست و از Property جهت مقدار دهی استفاده شده است.

Constructor

متد سازنده متدی است دقیقاً هم نام کلاس که به محض ساخت یک نمونه از کلاس اجرا می شود و مهمترین کاربرد آن مقدار دهی برخی فیلدها یا بررسی مواردی مانند، بررسی کانکشن، بررسی پایگاه داده و ... می باشد. متد سازنده متدی ویژه در برنامه نویسی سی شارپ می باشد که برای تعریف آن می بایست نکات زیر رعایت نمود.

  1. دقیقا هم نام کلاس باشد.
  2. حتما بصورت public تعریف شود.
  3. مقدار بازگشتی ندارد، حتی void هم نمی باشد.

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

public Time()
{
    Hour = 0;
    Minute = 0;
    Second = 0;
}

بهتر است تعریف متد سازنده، بلافاصله پس از تعریف فیلدها باشد.

Method Overloading

منظور از Method Overloading یا سربارگذاری متدها، تعریف متدهایی با نام یکسان اما ورودی متفاوت و طبیعتاً عملکرد متفاوت می باشد. این امر شاید کمی زحمت برنامه نویسی را افزایش دهد اما استفاده از کلاس طراحی شده را تسهیل کرده و موجب افزایش کارآیی آن می شود.

در این بخش قصد داریم برای متد سازنده ایجاد شده در مرحله قبل 3 حالت دیگر تعیین کنیم:

  1. کاربر بتواند هنگام ساخت نمونه از کلاس، ساعت را وارد کند.
  2. کاربر بتواند هنگام ساخت نمونه از کلاس، ساعت و دقیقه را وارد نماید.
  3. کاربر بتواند هنگام ساخت نمونه از کلاس، ساعت، دقیقه و ثانیه را وارد نماید.
public Time(int h)
{
    Hour = h;
    Minute = 0;
    Second = 0;
}
public Time(int h, int m)
{
    Hour = h;
    Minute = m;
    Second = 0;
}
public Time(int h, int m, int s)
{
    Hour = h;
    Minute = m;
    Second = s;
}

کدهای کامل کلاس Time پس از افزودن متدهای سربارگذاری شده به شکل زیر خواهد بود.

class Time
{
    int hour, minute, second;
    public Time()
    {
        Hour = 0;
        Minute = 0;
        Second = 0;
    }
    public Time(int h)
    {
        Hour = h;
        Minute = 0;
        Second = 0;
    }
    public Time(int h, int m)
    {
        Hour = h;
        Minute = m;
        Second = 0;
    }
    public Time(int h, int m, int s)
    {
        Hour = h;
        Minute = m;
        Second = s;
    }
    public int Hour
    {
        set
        {
            if (value >= 0 && value < 24)
            {
                hour = value;
            }
            else
            {
                hour = 0;
            }
        }
        get { return hour; }
    }
    public int Minute
    {
        set
        {
            if (value >= 0 && value < 60)
            {
                minute = value;
            }
            else
            {
                minute = 0;
            }
        }
        get { return minute; }
    }
    public int Second
    {
        set
        {
            if (value >= 0 && value < 60)
            {
                second = value;
            }
            else
            {
                second = 0;
            }
        }
        get { return second; }
    }

    public void ShowTime()
    {
        Console.WriteLine(Hour + ":" + Minute + ":" + Second);
    }
}

حال در متد Main هنگام ساخت نمونه از کلاس Time حالت زیر را مشاهده خواهید نمود.

آموزش سی شارپ- سربارگذاری متدها

تصویر فوق یعنی این متد به 4 حالت قابل استفاده می باشد که اولین حالت استفاده از آن بدون پارامتر می باشد.

کدهای موجود در Main را به شکل زیر اصلاح کنید.

class Program
{
    static void Main(string[] args)
    {
        Time t1 = new Time(14, 15, 30);
        t1.ShowTime();
        Console.ReadLine();
    }
}

مشاهده می کنید که سربارگذاری متد سازنده باعث شد استفاده از کلاس Time آسانتر شود.