کلاس‌ ها و اشیاء در C#

09 فروردین 1398
درسنامه درس 10 از سری آموزش سی شارپ (C#)
csharp-classes-objects

مطالعه‌ی فصول گذشته به شما کمک می‌کند تا مقدمات زبان برنامه‌نویسی C# را فراگرفته و در نهایت کدنویسی خود را آغاز کنید. در این فصل که به عنوان فصل ۹ مجموعه‌ی آموزشی C# شناخته می‌شود با مفاهیمی چون کلاس (Class) و اشیاء (Object) آشنا می‌شوید. توجه داشته باشید که تمام فضای زبان برنامه‌نویسی C# به صورت اشیاء و کلاس‌های مرتبط با آن است.

مقدمه

تعریف کلاس (Class): یک نوع داده‌ی دلخواه می‌باشد که توسط برنامه‌نویس تعریف می‌شود.

تعریف شیء (Object): یک شیء نمونه‌ای از یک کلاس می‌باشد.

تعریف متد: توابعی هستند که برخی عملیات‌ها را درون یک کلاس انجام می‌دهند و به عنوان عضوی از آن کلاس به حساب می‌آیند.

تعریف ویژگی: مشخصه‌هایی هستند که درون یک کلاس به عنوان متغییر ایفای نقش می‌کنند.

تعریف یک کلاس

در زبان برنامه‌نویسی C# کلاس‌ها با استفاده از کلمه‌ی کلیدی Class تعریف می‌شوند. و هر آنچه درون براکت پس از نام کلاس قرار می‌گیرد به عنوان بدنه‌ی کلاس شناخته می‌شود. هر کلاس شامل تعدادی متغییر و متد است. بنابراین ساختار کلی به صورت زیر می‌باشد:

<access specifier> class  ClassName
{
   // member variables
   <access specifier> <data type> variable1;
   <access specifier> <data type> variable2;
   ...
   <access specifier> <data type> variableN;
   // member methods
   <access specifier> <return type> method1(parameter_list)
   {
      // method body
   }
   <access specifier> <return type> method2(parameter_list)
   {
      // method body
   }
   ...
   <access specifier> <return type> methodN(parameter_list)
   {
      // method body
   }
}

در این ساختار شرح محتوا به صورت ذیل می‌باشد:

Access Modifier یا Access Specifier: در این قسمت تعیین سطح دسترسی کلاس مطابق با آنچه در فصل ۷ ذکر شد، صورت می‌پذیرد.

توجه به این نکته ضروری‌ست که سطح دسترسی پیش‌فرض کلاس‌ها به صورت Internal می‌باشد و سطح دسترسی پیشفرض برای متدها و اعضای درون کلاس Private است.

ClassName: نام کلاس می‌باشد که معمولا به صورت PascalCase تعریف می‌شود مثلا DbContext.

Data type: نوع داده‌ی متغییرها و متدهایی است که درون کلاس تعریف می‌شوند.

برای دستیابی به اعضای یک کلاس از علامت . استفاده می‌کنیم.

علامت دات (.) نام یک شیء را به نام یک عضو که شامل متد یا متغییر کلاس است، متصل می‌کند.

در مثال زیر کلاسی به نام Box تعریف کرده‌ایم که تنها دارای ۳ عضو متغییر به نام length، Breadth و height است. از طرفی پس از آن یک کلاس دیگر به نام Boxtester تعریف کرده و درون آن یک متد به نام Main ایجاد می‌کنیم. حال درون این متد ابتدا یک نمونه و شیء از کلاس Box ساخته و سپس آن را با علامت (.) دات مقدار دهی می‌کنیم:

using System;
namespace BoxApplication
{
    class Box
    {
       public double length;   // Length of a box
       public double breadth;  // Breadth of a box
       public double height;   // Height of a box
    }
    class Boxtester
    {
        static void Main(string[] args)
        {
            Box Box1 = new Box();   // Declare Box1 of type Box
            Box Box2 = new Box();   // Declare Box2 of type Box
            double volume = 0.0;    // Store the volume of a box here

            // box 1 specification
            Box1.height = 5.0;
            Box1.length = 6.0;
            Box1.breadth = 7.0;

            // box 2 specification
            Box2.height = 10.0;
            Box2.length = 12.0;
            Box2.breadth = 13.0;
           
            // volume of box 1
            volume = Box1.height * Box1.length * Box1.breadth;
            Console.WriteLine("Volume of Box1 : {0}",  volume);

            // volume of box 2
            volume = Box2.height * Box2.length * Box2.breadth;
            Console.WriteLine("Volume of Box2 : {0}", volume);
            Console.ReadKey();
        }
    }
}

خروجی این مثال به صورت زیر خواهد بود:

Volume of Box1 : 210
Volume of Box2 : 1560

سازنده‌ها در زبان C#

یک سازنده‌ی کلاس به عنوان متد یا تابع ویژه‌ایست که هنگام استفاده از آن کلاس قبل از تمام عناصر و متدها اجرا می‌شود. شیوه‌ی تعریف سازنده بدین‌صورت است که باید همواره همنام با کلاس بوده و با فرمت PascalCase نوشته شود. به مثال زیر توجه کنید:

using System;
namespace LineApplication
{
   class Line
   {
      private double length;   // Length of a line
      public Line()
      {
         Console.WriteLine("Object is being created");
      }

      public void setLength( double len )
      {
         length = len;
      }
      
      public double getLength()
      {
         return length;
      }

      static void Main(string[] args)
      {
         Line line = new Line();    
         
         // set line length
         line.setLength(6.0);
         Console.WriteLine("Length of line : {0}", line.getLength());
         Console.ReadKey();
      }
   }
}

در این مثال یک کلاس به نام Line ایجاد کرده‌ایم و سپس سازنده‌ی Line را پس از آن قرار داده‌ایم که درون این سازنده عبارت Object is being created چاپ می‌شود. بنابراین هنگامیکه در خط اصلی برنامه و در متد Main یک شیء از کلاس Line ایجاد می‌کنیم. در ابتدا سازنده فعال شده و مقدار Object is being created را چاپ می‌کند و خروجی به صورت زیر خواهد بود:

Object is being created
Length of line : 6

یک سازنده پیشفرض هیچ پارامتری ندارد و اگر بخواهیم آن را  آرگومان‌دهی کنیم می‌توان پارامتری را به آن اختصاص داد. در این صورت سازنده پیشفرض به سازنده دارای پارامتر تبدیل می‌شود:

using System;
namespace LineApplication
{
   class Line
   {
      private double length;   // Length of a line
      public Line(double len)  //Parameterized constructor
      {
         Console.WriteLine("Object is being created, length = {0}", len);
         length = len;
      }

      public void setLength( double len )
      {
         length = len;
      }
      public double getLength()
      {
         return length;
      }

      static void Main(string[] args)
      {
         Line line = new Line(10.0);
         Console.WriteLine("Length of line : {0}", line.getLength()); 
         
         // set line length
         line.setLength(6.0);
         Console.WriteLine("Length of line : {0}", line.getLength()); 
         Console.ReadKey();
      }
   }
}

در نهایت خروجی این مثال به صورت زیر خواهد بود:

Object is being created, length = 10
Length of line : 10
Length of line : 6

مخرب‌ها در C#

یک مخرب به عنوان متد یا تابعی ویژه درون یک کلاس ایفای نقش می‌کنند که به هنگام ساخت یک نمونه از آن کلاس و اتمام فرایندهای مربوطه نمایش داده می‌شود. به عبارت ساده تر سازنده ها در ابتدای برنامه و مخرب ها در انتهای برنامه اجرا می‌شوند. برای تعریف یک مخرب باید نامی دقیقا مشابه نام کلاس یا سازنده برای آن قرار داد و بدون هیچگونه تعین سطح دسترسی و تنها با علامت ‍~ آنها را ایجاد کرد. توجه داشته باشید که مخرب ها نه پارامتری را می‌پذیرند و نه مقداری را باز می‌گردانند. به مثال زیر توجه کنید:

using System;
namespace LineApplication
{
   class Line
   {
      private double length;   // Length of a line
      public Line()  // constructor
      {
         Console.WriteLine("Object is being created");
      }
      ~Line() //destructor
      {
         Console.WriteLine("Object is being deleted");
      }

      public void setLength( double len )
      {
         length = len;
      }
      
      public double getLength()
      {
         return length;
      }

      static void Main(string[] args)
      {
         Line line = new Line();
         
         // set line length
         line.setLength(6.0);
         Console.WriteLine("Length of line : {0}", line.getLength());           
      }
   }
}

در نهایت خروجی این برنامه به صورت زیر است:

Object is being created
Length of line : 6
Object is being deleted

اعضای Static در کلاس‌ها

برخی از اعضای یک کلاس را می‌توان به صورت static یا ساکن تعریف کرد. هنگامیکه این اتفاق بیافتید آن عضو تنها یک بار درون کل برنامه در دسترس خواهد بود. اگر بخواهیم یک مقایسه برای تفهیم بیشتر داشته باشیم می‌توان، اعضای استاتیک را مشابه اعضایی تعریف کرده که دارای یک مشخصه ثابت هستند و در طی برنامه مقادیر متفاوتی را به خود گرفته ولی آنها را حذف نمی‌کنند. به مثال زیر توجه کنید:

using System;
namespace StaticVarApplication
{
   class StaticVar
   {
      public static int num;
      public void count()
      {
         num++;
      }
      public int getNum()
      {
         return num;
      }
   }
   class StaticTester
   {
      static void Main(string[] args)
      {
         StaticVar s1 = new StaticVar();
         StaticVar s2 = new StaticVar();
         s1.count();
         s1.count();
         s1.count();
         s2.count();
         s2.count();
         s2.count();
         Console.WriteLine("Variable num for s1: {0}", s1.getNum());
         Console.WriteLine("Variable num for s2: {0}", s2.getNum());
         Console.ReadKey();
      }
   }
}

همانطور که در مثال فوق مشاهده می‌کنید عضو num از نوع int دارای ویژگی static است. حال در طی برنامه هنگامیکه وارد متد Main می‌شوید و یک شیء از کلاس StaticVar می‌سازید. با استفاده از از متد count سه واحد به مقدار موجوددر عضو num اضافه کرده و سپس مجددا با استفاده از متد count اما اینبار در شیء جدید s2 این افزایش واحد را داریم. حال که چاپ متغییر ها را انجام می‌دهیم متوجه خواهیم شد که مقدار num برابر عدد ۶ بوده. یعنی فرقی نمی‌کند که شیء ۱ یا شیء ۲ این افزایش واحد را انجام داده است. زیرا همواره مقدار آن اساتیک و ساکن می‌باشد. خروجی این مثال به صورت زیر است:

Variable num for s1: 6
Variable num for s2: 6

همچنین می‌توان یک متد یا تابع را درون یک کلاس به صورت static تعریف کرد. در این حالت باید درنظر داشته باشید که متدهای استاتیک فقط و فقط متغییرهای استاتیک را می‌پذیرند. از طرفی متد استاتیک قبل از اینکه یک شیء تعریف شود در دسترس است. یعنی متدهای استاتیک به گونه‌ای هستند که برای دسترسی به آنها نیازی به تعریف یک شیء نیست. به مثال زیر توجه کنید:

using System;
namespace StaticVarApplication
{
   class StaticVar
   {
      public static int num;
      public void count()
      {
         num++;
      }
      public static int getNum()
      {
         return num;
      }
   }
   class StaticTester
   {
      static void Main(string[] args)
      {
         StaticVar s = new StaticVar();
         s.count();
         s.count();
         s.count();
         Console.WriteLine("Variable num: {0}", StaticVar.getNum());
         Console.ReadKey();
      }
   }
}

در نهایت خروجی این مثال به صورت زیر خواهد بود:

Variable num: 3

بسیار عالیست به شما تبریک می‌گوییم. در این شما با مفاهیم شیءگرایی و کلاس‌ها در زبان برنامه‌نویسی سی شارپ آشنا شدید. این قدم مهم ترین گام برای ورود به دنیای برنامه‌نویسی حرفه‌ای به حساب می‌آید. در فصل آینده در ارتباط با مفهوم Inheritance (ارث‌بری) آشنا خواهیم شد. با ما همراه باشید.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش سی شارپ (C#) توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.