ایران سرفراز- نرم افزار وپروژهای دانشجویی


نرم افزار وپروژهای دانشجویی

فصل پنجم کلاسها و اشیاءدر #c

<!-- /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;} div.Section1 {page:Section1;} -->

فصل پنجم Mohsen_mahyar@yahoo.com

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

آنچه که در این فصل یاد خواهید گرفت:

نحوهی تعریف یک کلاس و استفاده از آن

معرفهای دسترسی و تاثیر آنها روی اعضای کلاس

سازندهها و مخرب کلاس

اعضای نمونه و ایستای کلاس و تفاوتهای کاربردی آنها

تخصیص حافظه به نمونههای کلاس

this • کلمهیکلیدی

صحبت کردیم. به یاد دارید که این انواع داده برای (#c در فصلهای قبلی در مورد انواع داده درونی (ساخته شده در

تعریف انواع داده جدید برای انطباق با #c نگهداری و دستکاری مقادیر عددی و رشتهای استفاده میشدند. قدرت واقعی

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

انواع دادهی جدید را مشخص میکنید.

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

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

میتوانید کار کنید.

یک کلاس سگ شرح میدهد، آنها چه چیزهای مشابهی دارند. آنها وزن، طول، رنگ چشم، رنگ مو، مزاج و غیره دارند. آنها

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

چشم و مو و مزاج خاصی دارد.

مزیت بزرگ برنامهنویسی شیگرا آن است که کلاسها، ویژگیها و تواناییهای یک نوع داده را در یک واحد منحصر به فرد و

تودار کپسوله میکنند.

به عنوان ListBox ویندوز را مرتب کنید. کنترل ListBox برای مثال، فرض کنید میخواهید محتویات یک نمونه از کنترل

یک کلاس تعریف میشود. یکی از ویژگیهای کلاس این است که آن میداند چگونه خود را مرتب کند. مرتبسازی در کلاس

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

خودش را مرتب کند. شما خود را با نحوهی مرتبسازی آن درگیر نمیکنید. این همان کپسولهکردن است.

فصل چهار-برنامه نویسی شی گرا

87

را برای تعریف کلاسهای جدید شرح میدهد. اجزاء یک کلاس از قبیل رفتارهای آن و حالت #C این فصل ویژگیهای زبان

آن به اعضای کلاس معروف هستند. رفتار کلاس با نوشتن متدها ایجاد میشود. یک متد امر عادی است که هر شیئی از آن

میتواند ListBox داشته باشد و کلاس Bark میتواند متدی به نام Dog کلاس میتواند اجرا کند. برای مثال، یک کلاس

داشته باشد. Sort متدی به نام

حالت کلاس با فیلدها نگهداری میشود. ممکن است فیلدها از انواع داده اولیه یا اشیائی از کلاسهای دیگر باشند.

در نهایت، ممکن است کلاس خصوصیاتی داشته باشد که برای سرویسدهنده شبیه متد ها عمل میکنند، اما برای

سرویسگیرندهی کلاس شبیه فیلدهای کلاس به نظر میرسند. یک سرویس گیرنده، شیئی است که با هر نمونه از کلاسی

تعامل دارد .

-1-5 تعریف کلاس

در زمان تعریف یک کلاس، ویژگیهای همه اشیاء کلاس را به خوبی رفتارهایشان تعریف میکنید. برای مثال، اگر پنجرهسازی

ListBox سیستمعامل خودتان را ایجاد میکنید، ممکن است بخواهید چیزهای صفحه نمایش را ایجاد کنید. کنترل جالب

ها ویژگیهای متعددی همچون ListBox . در نمایش لیستی از انتخابها و توانایی کاربر برای انتخاب از لیست مفید است

طول، عرض، موقعیت و رنگ متن دارند.

برنامهنویسها رفتارهای معینی از کادرلیست 1ها انتظار دارند. آنها میتوانند باز، بسته، مرتب و غیره شوند.

ایجاد کنید که این ویژگیها و تواناییها را ListBox برنامهنویسی شیگرا به شما اجازه میدهد نوع دادهی جدیدی بنام

کپسوله میکند.

برای تعریف یک نوع داده یا کلاس جدید، ابتدا آن را اعلان کرده و سپس متدها و فیلدهای آن را تعریف کنید. یک کلاس را

اعلان کنید. گرامر کامل آن به صورت زیر است. class با استفاده از کلمهی کلیدی

[attributes ] [access-modifiers] class identifier [:base-class] {class-body}

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

نیاز ندارید. معرفهای دسترسی بعدا بررسی میشوند ( معمولا کلاسهای شما از کلمه کلیدی #C را برای برنامهنویسی عادی

به عنوان معرف دسترسی خود استفاده میکنند). public

با اسامی نامگذاری میشوند ( سگ، کارمند، کادرلیست ). قوانین #C شناسهی 3 کلاس همان نام کلاس است. کلاسهای

نامگذاری از نمادگذاری پاسکال استفاده میکنند. در نمادگذاری پاسکال خط فاصله یا زیرخط استفاده نمیکنند و در

.(GoldenRetriever) شناسههای یک یا چندکلمهای، حرف اول هر کلمه را بزرگ مینویسند

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

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

class Dog

{

int age; // the dog's age

int weight; // the dog's weight

Bark( ) { //... }

1 listBox

2 Attributes

3 identifier

Mohsen_mahyar@yahoo.com - C# برنامه نویسی

88

Eat( ) { // ... }

}

همه رفتار سگ را شرح میدهند. فیلدهایی همچون سن و وزن، حالت یا همه ،Dog متدهای موجود در تعریف کلاس

خصوصیات سگ را شرح میدهند.

-1 نمونهسازی 1 اشیاء -1 -5

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

مرحله برای ایجاد یک شی یا نمونهسازی لازم هستند. برای اعلان یک شی، ابتدا نام کلاس و به دنبال آن نام شی را

بنویسید.

Dog milo; // declare milo to be an instance of Dog

استفاده میکنیم. پس نام یک Camel این عمل به ایجاد یک متغیر محلی شباهت ندارد. در تعریف شی از قرارداد نمادگذاری

باشد. myDog متغیر یا شی میتواند مانند

عمل اعلان به تنهایی یک نمونهی واقعی ایجاد نمیکند. برای ایجاد یک نمونه از یک کلاس، باید با استفاده از کلمه کلیدی

به آن شی حافظه تخصیص دهیم. new

milo=new Dog();//allocate memory for milo

میتوانید اعلان یک شی و تخصیص حافظه به آن را ترکیب کنید و در یک خط بنویسید.

;() Dog milo=new Dog

را ایجاد میکند. دلیل وجود پرانتزها Dog اعلان میکند و یک نمونهی جدید از Dog را به عنوان شیئی از نوع milo این کد

را بعدا خواهید فهمید.

نقطهی ورود ()Main هر چیزی بوسیلهی یک کلاس اتفاق میافتد. هیچ متدی نمیتواند خارج از کلاس اجرا شود. متد #C در

برنامه ی شما است، که به وسیلهی سیستم عامل فراخوانی میشود و آن جایی است که اجرای برنامه آغاز میشود. شما یک

شبیه هر متد دیگر باید در یک کلاس باشد. ()Main ایجاد خواهید کرد، چون متد ()Main کلاس کوچک برای جا دادن متد

public class Tester

{

public static void Main( )

{

//...

}

}

ندارید. برای این Tester ایجاد شده است، شما هنوز هیچ نمونهای از نوع ()Main برای جا دادن متد Tester اگرچه کلاس

کار خواهیم نوشت:

;()Tester myTester = new Tester

فراخوانی متدهای دیگر کلاس را از طریق شی ایجادشده ممکن میسازد. ،Tester ایجاد یک نمونه از کلاس

1 Instantiate

فصل چهار-برنامه نویسی شی گرا

89

Time -2 ایجاد کلاس -1 -5

حال، کلاسی که زمان را پیگیری و نمایش میدهد، ملاحظه کنید. حالت داخلی کلاس باید قادر به نمایش سال، ماه، روز،

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

فراهم کرده است. DataTime یک کلاس عملیاتی به نام NET. چارچوب

1) پیادهسازی کنید. - شما این کلاس را با تعریف یک متد و 6 متغیر ( مثال 5

Time 1 کلاس - مثال 5

using System;

public class Time

{

// private variables

private int year;

private int month;

private int date;

private int hour;

private int minute;

private int second;

// public methods

public void DisplayCurrentTime( )

{

Console.WriteLine( "stub for DisplayCurrentTime" );

}

}

public class Tester

{

static void Main( )

{

Time timeObject = new Time( );

timeObject.DisplayCurrentTime( );

}

}

second با اعلان تعدادی متغیر عضو Time ایجاد میکند. تعریف کلاس Time این کد یک نوع داده جدید کاربری به نام

شروع میشود. ,minute ,hour ,day ,month ,year

تعیین میکند که این فیلدها فقط در متدهای داخل کلاس قابل استفاده هستند. کلمه کلیدی private کلمهی کلیدی

یک معرف دسترسی است . private

ترجیح میدهند اعلان فیلدها در کنار هم ( بالا یا پایین) کلاس قرار گیرند. البته #C بیشتر برنامه نویسان

ضروری نیست.

بر میگرداند، به عبارت void است. این متد مقدار DisplayCurrentTime متد ،Time تنها متد اعلانشده در کلاس

دیگر هیچ مقدار برگشتی ندارد.

اسلام احمد زاده - 09177112161 - C# برنامه نویسی

90

ممکن است بخواهیم در ابتدای برنامهنویسی، ساختار کلی برنامه را بدون در نظر گرفتن جزئیات آن ایجاد کنیم، در اینصورت

که فقط DisplayCurrentTime یک دستور ساده در متدها مینویسیم که نشاندهندهی اجرای این متد باشد. مانند متد

یک پیام را در خروجی چاپ میکند.

بنام Time یک نمونه از ()Main را در بردارد. در ()Main تعریف میشود که متد Tester کلاس ،Time بعد از کلاس

ایجاد میشود. timeObject

Time timeObject = new Time( );

آن شی DisplayCurrentTime میتواند از متد ()Main است، متد Time یک نمونه از کلاس timeObject چون

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

timeObject.DisplayCurrentTime( );

متدی از یک کلاس را با نوشتن نام شی و به دنبال آن نام متد (که با نقطه از هم جدا شده اند)، می توان احضار کرد و

پارامترهای متد در داخل پرانتزها قرار میگیرند. اگر متدی پارامتر نداشته باشد، پرانتز خالی نیز اجباری است.

-3 معرفهای دسترسی -1 -5

1 معرفهای - یک معرف دسترسی نحوه دستیابی به اعضای کلاس، از بیرون یا داخل کلاس را تعیین میکند. جدول 6

را خلاصه میکند. #C دستیابی

1- معرفهای دستیابی - جدول 5

معرف دسترسی محدودیتها 1

علامتگذاری شدهاند، برای هر متد از public بدون محدودیت. اعضایی که با public

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

این اعضا فقط به متدهای همان کلاس نمایان هستند. private

این اعضا برای متدهای همان کلاس و کلاسهایی که از آن مشتق شدهاند، protected

نمایان هستند

برای همه کلاسهای موجود در اسمبلی مربوطه نمایان هستند internal

Protected

Internal برای متدهای همان کلاس و کلاسی که از آن مشتق شده و در اسمبلی مربوطه

قرار دارند، نمایان است.

بخشی از واسط عمومی کلاس هستند. آنها نحوهی رفتار کلاس را تعریف public متدهای

میکنند.

برای انجام کاری استفاده public متدهای کمکی هستند که توسط متدهای private متدهای

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

کلاسهای دیگر نمایان باشند.

1 Restrictions

فصل چهار-برنامه نویسی شی گرا

91

توجه: اگر چند معرف دسترسی در چندین سطح روی یک عنصری اعمال شوند، محدودترین آنها در نظر

گرفته میشود.

اعلان میشوند تا هر کلاس دیگر بتواند از آن استفاده کند. public هر دو ()DisplayCurrentTime و متد Time کلاس

2- باشد، در این حالت متدهای مربوط به کلاسهای دیگر نمیتوانند آنرا احضار کنند. در مثال 6 private اگر متد مورد نظر

احضار شده است. این عمل معقول است، چون کلاس Tester از طریق یک متد کلاس ()DisplayCurrentTime متد

علامتگذاری شدهاند. public هر دو بصورت DisplayCurrentTime و متد Time

-2-5 آرگومانهای متد

رفتار یک کلاس با متدهای آن کلاس تعریف میشود. برای انعطافپذیر کردن متدها، میتوانید پارامترهایی را تعریف کنید.

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

پارامتری تعریف کنید که نوع عمل مرتبسازی را به آن ارسال ()Sort میتوانید در متد ،ListBox صعودی و نزولی یک

کند.

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

بر void تعریف میکند که مقدار ()MyMethod قبل از نام آن پارامتر تعیین میشود. برای مثال، اعلان زیر یک متد به نام

میگرداند و دو پارامتر میگیرد.

void MyMethod (int firstParam, Button secondParam)

{

// ...

}

2 نحوهی ارسال مقادیر به یک متد را نشان میدهد. - در بدنهی متد، پارامترها همانند متغیرهای محلی عمل میکنند. مثال 5

2- مثال 5

using System;

public class MyClass

{

public void SomeMethod( int firstParam, float secondParam )

{

Console.WriteLine("Here are the parameters received: {٠}, {١}",firstParam,

secondParam );

}

}

public class Tester

{

static void Main( )

{

int howManyPeople = ۵;

float pi = ٣٫١۴f;

MyClass mc = new MyClass( );

mc.SomeMethod( howManyPeople, pi );

}

}

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

Here are the parameters received 5،3,14

ایجاد و مقداردهی اولیه میشوند. این متغیرها به pi و howManyPeople دو متغیر محلی (Main) در متد فراخوانیکننده

را به pi و firstParam را به howManyPeople ارسال میشوند. کامپایلر متغیر SomeMethod عنوان پارامترهایی به

نگاشت میکند. secondParam

Mohsen_mahyar@yahoo.com - C# برنامه نویسی

92

-3-5 سازندهها

است. ()Time شبیه احضار متد Time 1 دستور ایجاد شیئی از نوع - توجه کنید که در مثال 6

Time timeObject = new Time( );

در واقع در زمان نمونهسازی یک شی، یک متد احضار میشود، این متد سازنده نامیده میشود. زمان تعریف یک کلاس،

تعریف سازندهی آن دلخواه است. اما اگر این کار را انجام ندهید، کامپایلر یک سازندهی پنهان و اتوماتیک فراهم خواهد کرد.

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

حافظه است، بعد از اجرای سازنده، حافظه یک نمونهی معتبر از کلاس را نگه میدارد.

سازنده تعریف نمیکند، پس کامپایلر به طور اتوماتیک آن را ایجاد میکند. سازندهی فراهم شده ،Time 2 کلاس - در مثال 5

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

است. سازندهی فراهم شده توسط کامپایلر هیچ آرگومانی ندارد.

2 - اگر شما متغیرهای عضو را به طور صریح مقداردهی اولیه نکنید، آنها به مقادیر بیضرر مقداردهی اولیه میشوند. جدول 5

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

2- جدول 5

نوع داده مقدار پیش فرض

عددی صفر

flase bool

null \0 char

0 Enum

null Refrence

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

3 می توانید برای ایجاد یک شی با دادهی بامعنی، مقادیر سال، ماه و روز جاری را به سازنده ارسال کنید. - کند. در مثال 5

یک سازنده را شبیه هر متد دیگر اعلان کنید به استثناء موارد زیر:

-1 نام سازنده باید هم نام کلاس باشد.

-2 سازنده ها مقدار بازگشتی ندارند.

3 یک - اگر بخواهید آرگومانهایی را به سازنده ارسال کنید، لیست آرگومانها را شبیه هر متد دیگر اعلان کنید. مثال 5

اعلان میکند که 6 آرگومان میپذیرد. Time سازنده برای کلاس

3- مثال 5

using System;

public class Time

{

// private member variables

int year;

int month;

int date;

int hour;

فصل چهار-برنامه نویسی شی گرا

93

int minute;

int second;

// public method

public void DisplayCurrentTime( )

{

System.Console.WriteLine( "{٠}/{١}/{٢} {٣}:{۴}:{۵}", month, date, year, hour,

minute, second );

}

// constructor

public Time( int theYear, int theMonth, int theDate,int theHour, int theMinute,

int theSecond )

{

year = theYear;

month = theMonth;

date = theDate;

hour = theHour;

minute = theMinute;

second = theSecond;

}

}

public class Tester

{

static void Main( )

{

Time timeObject = new Time( ٢٠٠٨, ٨, ١, ٩, ٣۵, ٢٠ );

timeObject.DisplayCurrentTime( );

}

}

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

9:35:20 2008/1/8

در این مثال، سازنده یک دنباله از اعداد صحیح را گرفته و همه متغیرهای عضو را براساس این پارامترها مقداردهی اولیه

میکند.

وجود دارد و مقادیر آن مقداردهی اولیه شدهاند. زمانی که متد Time زمانی که سازنده پایان مییابد، شی

فراخوانی میشود، مقادیر نمایش داده میشوند. اگر متغیر عددی را مقداردهی ()Main در ()DisplayCurrentTime

نکنید، توسط کامپایلر به مقدار صفر مقداردهی اولیه میشود. به یاد دارید که انواع دادهی مقداری باید مقداردهی اولیه شده

باشند، در غیر اینصورت سازنده به آنها مقادیر بیضرر میدهد.

-4 مقداردهندههای اولیه 1 -5

مقداردهی اولیه متغیرهای عضو بوسیلهی یک مقدار اولیه دهنده امکانپذیر است. به جای مقداردهی اولیه در سازنده، یک

مقداردهنده اولیه را با تخصیص یک مقدار اولیه به یک عضو کلاس ایجاد میکنید.

Private int second =30 ; //intializer

Time مقدار زمان مهم نیست، اما ثانیهها همواره به مقدار 30 مقداردهی اولیه میشوند. شاید کلاس Time فرض کنید در شی

4را بینید . - را مشخص کند. مثال 5 Second را رونویسی کنید تا یک مقداردهنده اولیه ، مقدار

4- مثال 5

using System;

public class Time

{

// private member variables

1 Initializers

Mohsen_mahyar@yahoo.com- C# برنامه نویسی

94

int year;

int month;

int date;

int hour;

int minute;

int second = ٣٠;

// public method

public void DisplayCurrentTime( )

{

System.Console.WriteLine( "{٠}/{١}/{٢} {٣}:{۴}:{۵}",month, date, year, hour,

minute, second );

}

// constructor

public Time( int theYear, int theMonth, int theDate,int theHour, int theMinute )

{

year = theYear;

month = theMonth;

date = theDate;

hour = theHour;

minute = theMinute;

}

}

public class Tester

{

static void Main( )

{

Time timeObject = new Time( ٢٠٠٨, ٨, ١, ٩, ٣۵ );

timeObject.DisplayCurrentTime( );

}

}

خروجی شبیه زیر است

9:35:30 2008/1/8

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

به 30 مقدار دهی اولیه می شود. Second

Second در بخش بعدی خواهیم دید که میتوانید بیش از یک سازنده داشته باشید. اگر بخواهید در بیش از یک مورد از آنها

را به 30 مقداردهی اولیه کنید، به جای مقداردهی اولیه جداگانه در هر سازنده، استفاده از مقدار دهنده اولیه بهترین راه

است.

this -5-5 کلمه کلیدی

یک پارامتر پنهان در هر متد غیرایستای یک this به نمونه جاری از یک شی ارجاع میکند. ارجاع this کلمه کلیدی

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

پارامترهای هم نام با اعضای نمونهی کلاس است.

public void SomeMethod (int hour)

{

this.hour = hour;

}

برای حل این ابهام بکار برده this یک پارامتر هم نام عضوی از کلاس میگیرد. ارجاع SomeMethod در این مثال متد

به پارامتر ارجاع میکند. hour به متغیر عضو و this.hour . میشود

را برای انتساب صریح بکار برید. this می توانید ارجاع

فصل چهار-برنامه نویسی شی گرا

95

public void SetTime(year, month, date, newHour, newMinute, newSecond)

{

this.year = year; // use of "this" required

this.month = month; // required

this.date = date; // required

this.hour = hour; // use of "this" optional

this.minute = newMinute; // optional

second = newSecond; // also ok

}

ضروری ____________است، در غیر اینصورت اختیاری this در صورتی که یک پارامتر با عضوی از کلاس هم نام باشد، استفاده از

میباشد.

برای ارسال شی جاری به عنوان پارامتر به متد دیگری میباشد. به عنوان مثال : this کاربرد دوم ارجاع

Class SomeClass

{

public void FirstMethod(OtherClass otherObject)

{

otherObject.SecondMethod(this);

}

// ...

}

و FirstMethod یک متد بنام OtherClass. SomeClass و SomeClass : این قطعه کد دو کلاس را بنا مینهد

را احضار کرده و شی جاری SecondMethod متد ،FirstMethod دارد. متد SomeMethod یک متد بنام OtherClass

را به عنوان پارامتر به آن ارسال میکند. this را برای پردازش بعدی به آن ارسال میکند. برای این کار، ارجاع

ها است . indexer در this کاربرد دیگر

-6-5 اعضای نمونه و ایستا

فیلدها، خصوصیات و متدهای یک کلاس میتوانند اعضای نمونه 1 یا اعضا ایستا 2 باشند. اعضای نمونه به نمونههای یک نوع

داده اختصاص داده میشوند، در حالیکه اعضای ایستا به کلاسی اختصاص داده میشوند و به نمونه خاصی از کلاس اختصاص

با آنها بکار static داده نمیشوند. متدها بطور پیش فرض متدهای نمونه هستند، مگر اینکه به طور واضع کلمهی کلیدی

برده شود.

اکثریت متدها، متدهای نمونه خواهند بود. متد نمونه بدین معنی است که یک عمل روی یک شی خاصی رخ میدهد. در حال

حاضر به منظور توانایی احضار یک متد بدون داشتن یک نمونه از آن مناسب است که متد ایستا تعریف کنید.

دارید و Button بعد از اعلان یک کلاس، دسترسی به عضو ایستای آن ممکن است. برای مثال، فرض کنید یک کلاس بنام

را دارید. bthDelete و btnUpdate اشیای معرفی شده از این کلاس به نام های

()Draw دارد. کار متد ()GetButtonCount و یک متد ایستا به نام ()Draw یک متد نمونه بنام Button فرض کنید کلاس

برگرداندن تعداد دکمههای قابل رویت روی فرم است. GetButtonCount ترسیم دکمه جاری است و کار متد

دسترسی به یک متد نمونه از طریق یک نمونه از آن شی انجام میشود.

btnUpdate.SomeMethod( );

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

Button.GetButtonCount( );

1 Instance

2 Static

Mohsen_mahyar@yahoo.com - C# برنامه نویسی

96

-1-6 احضار متدهای ایستا -5

را بکار برند، this متدهای ایستا به جای یک نمونه از کلاس روی یک کلاس عمل میکنند. آنها نمیتوانند کلمهی کلیدی

چون هیچ شی جاری در کار نیست.

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

بخواهد به متد غیر ایستای هر کلاسی دسترسی داشته باشد، باید یک نمونه از آن کلاس را معرفی کند. ()Main است. اگر

یک VS.NET . ایجاد کنید StaticTester 2005 را استفاده کرده و یک برنامه کاربردی کنسولی بنام vs برای مثال بعدی

تغییر نام دهید و همه Tester 1 را به Class . 1 ایجاد میکند Class و یک کلاس به نام StaticTester فضای نامی

را از متد args قرار میدهد حذف کنید. پارامتر ()Main در بالای VS NET را که [STATThread] توضیحات و صفت

حذف کنید. بعد از این کارها، کد شما به صورت زیر میباشد: ()Main

using System;

namespace StaticTester

{

class Tester

{

static void Main( )

{

}

}

}

()Run انجام میشد، اما حالا یک متد نمونه بنام ()Main آن نقطه شروع خوبی است. تا به حال، همه کارهای برنامه در متد

انجام خواهد شد. ()Run ایجاد خواهیم کرد. کار برنامه در متد

را نوشته و به public معرف دسترسی ،Run را در داخل کلاس اعلان کنید. در اعلان متد ()Run متد نمونه جدید به نام

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

public void Run( )

هیچ پارامتری ندارد. پس میتوانید پرانتز ها را خالی رها کنید. آکولادها ()Run پرانتزها، پارامترها را نگه خواهند داشت، اما

روی کنسول را بنویسید. "Hello world" را برای متد باز کرده و دستور چاپ

public void Run( )

{

Console.WriteLine("Hello world");

}

را احضار کند. بنابراین یک نمونه ()Run یک متد ایستا است. پس نمیتواند مستقیما ( )Main یک متد نمونه است و ( )Run

را روی آن نمونه فراخوانی خواهید کرد. ()Run را ایجاد خواهید کرد و Tester از کلاس

;( )Tester t=new Tester

1- شکل 5

فصل چهار-برنامه نویسی شی گرا

97

را تایپ میکنید، سیستم هوشمند 1 سعی میکند با نام کلاس به شما کمک کند. در خط بعدی متد new زمانی که کلمه کلیدی

سیستم هوشمند لیست متدهای ،t احضار کنید. هنگام تایپ عملگر نقطه بعد از Tester از کلاس t ر ا روی شی ( )Run

را نمایش میدهد. Tester کلاس

5 خواهد شد. - زمانی که برنامه شما کامل شد، شبیه مثال 5

5- مثال 5

using System;

namespace StaticTester

{

// create the class

class Tester

{

// Run is an instance method

public void Run( )

{

Console.WriteLine( "Hello world" );

}

// Main is static

static void Main( )

{

// create an instance

Tester t = new Tester( );

// invoke the instance method

t.Run( );

}

}

}

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

Hello world

به معرفی یک شی محدود میشود و سپس متد ()Main این مدل را در بیشتر برنامههای کنسولی بکار خواهید برد. متد

را احضار میکند. ()Run

1 Intellisense

Mohsen_mahyar@yahoo.com - C# برنامه نویسی

98

-2-6 کاربرد فیلدهای ایستا -5

یک کاربرد عمومی متغیرها یا فیلدهای ایستا، نگهداری تعداد نمونههای جاری موجود از یک کلاس است. در مثال بعدی، یک

را برای شبیهسازی یک فروشگاه حیوانات اهلی ایجاد خواهید کرد. Cat شی از کلاس

6 نشان داده میشود. - آمده است. لیست کامل برنامه در مثال 5 Cat در این مثال، فقط خصوصیات ضروری کلاس

6- مثال 5

using System;

namespace Test

{

// declare a Cat class

// stripped down

public class Cat

{

// a private static member to keep

// track of how many Cat objects have

// been created

private static int instances = ٠;

private int weight;

private String name;

// cat constructor

// increments the count of Cats

public Cat( String name, int weight )

{

instances++;

this.name = name;

this.weight = weight;

}

// Static method to retrieve

// the current number of Cats

public static void HowManyCats( )

{

Console.WriteLine( "{٠} cats adopted", instances );

}

public void TellWeight( )

{

Console.WriteLine( "{٠} is {١} pounds", name, weight );

}

}

class Tester

{

public void Run( )

{

Cat.HowManyCats( );

Cat frisky = new Cat( "Frisky", ۵ );

frisky.TellWeight( );

Cat.HowManyCats( );

Cat whiskers = new Cat( "Whisky", ٧ );

whiskers.TellWeight( );

Cat.HowManyCats( );

}

static void Main( )

{

Tester t = new Tester( );

t.Run( );

}

}

}

خروجی :

فصل چهار-برنامه نویسی شی گرا

99

٠ cats adopted

Frisky is ۵ pounds

١ cats adopted

Whisky is ٧ pounds

٢ cats adopted

شروع میشود، که با صفر مقداردهی اولیه میشود. این فیلد ایستا instances با تعریف یک فیلد ایستا بنام Cat کلاس

ایجاد شده را نگه میدارد. هر زمان که سازنده اجرا میشود، مقدار آن یک واحد افزایش مییابد. Cat تعداد اشیاء

را پیگیری Cat این دو فیلد نام و وزن تک به تک اشیاء .name , weight : دو فیلد نمونه تعریف میکند Cat کلاس

میکنند.

ایستا است. تعدادگربهها ()HowManyCats تعریف میکند. متد ()TellWeight() ,HowManyCats دو متد Cat کلاس

یک متد نمونه است، چون هر ()TellWeight یک خصوصیت از یک گربه نیست. آن یک خصوصیت از کل کلاس است. متد

دستیابی میکند. HowManyCats مستقیما به متد Cat از طریق کلاس ( )Main گربه نام و وزن خودش را دارد. متد

Cat.HowManyCats( );

دستیابی میکند. ()TellWeight به متد نمونه Cat ایجاد میکند و از طریق نمونهی Cat یک نمونه از ()Main سپس

Cat frisky = new Cat( )

frisky.TellWeight( );

افزایش گربه ها را گزارش میدهد. ()HowManyCats . ایجاد میشود Cat هر زمانی که یک نمونه از کلاس

-7-5 خراب کردن اشیاء

و پاسکال )، جمع آوری زباله را فراهم میکند. بعد از کار بر روی اشیاء، (++c,c برخلاف بیشتر زبانهای برنامهنویسی #C

آنها بطور اتوماتیک خراب میشوند و نیازی نیست نگران پاکشدن اشیاء باشید. مگر اینکه منابع مدیریتنشده یا نادر 1

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

.(

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

فراهم میشود که در حین خراب کردن شی به وسیله جمعکنندهی زباله فراخوانی میشود.

اعلان کنید. ˜ را با علامت #C مخرب

˜{ } MyClass

این گرامر توسط کامپایلر به صورت زیر ترجمه میشود.

protected override void Finalize()

{

try

{

// do work here

}

finally

{

base.Finalize();

}

}

1 Scarce

Mohsen_mahyar@yahoo.com - C# برنامه نویسی

100

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

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

پیادهسازی کنید که به Dispose را پیادهسازی کنید. بدین منظور لازم است یک متد به نام IDisposable شما باید واسط

وسیله سرویسگیرندهها فراخوانی خواهد شد.

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

را به عنوان پارامتر this را فراخوانی کنید و ()GC.SuppressFinalize متوقفکردن جمعکنندهی زباله متد ایستای

شما را فراخوانی کند، احتمالا می نویسید: ()Dispose به آن ارسال کنید. پس مخرب شی میتواند متد

using System;

class Testing : IDisposable

{

bool is_disposed = false;

protected virtual void Dispose( bool disposing )

{

if ( !is_disposed ) // only dispose once!

{

if ( disposing )

{

Console.WriteLine( "Not in destructor,

OK to reference other objects" );

}

// perform cleanup for this object

Console.WriteLine( "Disposing..." );

}

this.is_disposed = true;

}

public void Dispose( )

{

Dispose( true );

// tell the GC not to finalize

GC.SuppressFinalize( this );

}

~Testing( )

{

Dispose( false );

Console.WriteLine( "In destructor." );

}

}

خصوصی و یک ()Dispose را فراخوانی میکنند. میتوانید یک متد ()Close در بعضی از اشیاء، سرویس گیرنده ها متد

را احضار کنید. ()Dispose متد ()Close ایجاد کنید و در متد ()Close متد عمومی

برای using یک دستور #C ، توسط کاربر برنامه و اتمام غیرقطعی برنامه ()Dispose به دلیل عدم اطمینان از فراخوانی

در نزدیکترین زمان ممکن فراهم میکند. برای اشیایی که به کار میبرید، برای آنها در ()Dispose اطمینان از فراخوانی

به طور اتوماتیک روی آن شی ()Dispose بین آکولادها یک میدان ایجاد میکنید. زمانی که به آکولاد بسته رسیدیم، متد

فراخوانی خواهد شد. همانطور که در اینجا میبینید :

using System.Drawing;

class Tester

{

public static void Main( )

{

using (Font theFont = new Font("Arial", ١٠٫٠f))

{

// use the font

}

1 Finalizer

فصل چهار-برنامه نویسی شی گرا

101

}

}

را مجاز میدارد، ما میخواهیم در نزدیکترین فرصت آن را از بین ببریم. در این Font چون ویندوز فقط تعداد کمی از اشیاء

روی ()Dispose پایان مییابد، فراخوانی using ایجاد میشود. زمانی که دستور using با دستور Font قطعه کد، شی

تضمین میشود. ()Font شی

-8-5 تخصیص حافظه

اشیاء ایجاد شده در متدها، متغیرهای محلی خوانده میشوند. آنها در متد به صورت محلی هستند. شی ایجاد شده در متد،

در همان متد استفاده میشود و در زمان پایان متد خراب میشود. اشیاء محلی، بخشی از حالت شی نیستند، آنها مقادیر

موقت را نگه میدارند.

ایجاد میشوند. زمانی که متدها احضار Stack روی بخشی از حافظه بنام int متغیرهای محلی انواع داده اصلی، همچون

به پارامترها و متغیرهای محلی آنها حافظه تخصیص داده میشود و در انتهای متد آزاد میشود. Stack میشوند،در روی

ایجاد میشوند. زمانی که متد پایان مییابد، متغیرهای Stack زمانی که یک متد شروع میشود، همه متغیر های محلی روی

محلی خراب میشوند.

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

مییابد، متغیر از میدان بیرون رفته و خراب میشود.

ایجاد میشوند. همه انواع Stack انواع دادهها را به دو گروه مقداری و ارجاعی تقسیم میکند. انواع دادهی مقداری روی #C

ایجاد میشوند. Stack انواع داده مقداری هستند و روی (long , int) داده اصلی

ایجاد میشوند. Heap کلاسها انواع دادهی ارجاعی هستند. انواع داده ارجاعی روی یک بلاک مشتق شده از حافظه بنام

زمانی که یک نمونه از نوع داده ارجاعی اعلان میکنید، در واقع یک متغیر به یک شی دیگر اشاره میکند. ارجاع، همانند

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

;( )Dog milo=new Dog

انتساب داده milo ایجاد میکند و یک ارجاع به آن بر میگرداند. آن ارجاع به Heap روی Dog یک شی new عملکرد

اشاره میکند. اما از نظر تکنیکی آن نادرست Heap روی Dog یک شی ارجاعی است که به یک شی milo میشود. بنابراین

همانند milo اشاره میکند. ارجاع Heap بدون نام ) روی ) Dog یک شی ارجاعی است که به یک شی milo است. در واقع

برخورد میگردد. Dog همانند خود شی milo یک نام مستعار برای شی بدون نام عمل میکند. در اهداف عملی با

مفهوم کاربرد ارجاعها این است که میتوانید به یک شی چندین ارجاع داشته باشید. برای فهم تفاوت ما بین انواع داده

7 را بررسی کنید. تحلیل کامل به دنبال مثال میآید. - مقداری و ارجاعی مثال 5

7- مثال 5

using System;

namespace heap

{

public class Dog

{

public int weight;

}

class Tester

{

public void Run( )

{

// create an integer

Mohsen_mahyar@yahoo.com - C# برنامه نویسی

102

int firstInt = ۵;

// create a second integer

int secondInt = firstInt;

// display the two integers

Console.WriteLine( "firstInt: {٠} secondInt: {١}",firstInt, secondInt );

// modify the second integer

secondInt = ٧;

// display the two integers

Console.WriteLine( "firstInt: {٠} secondInt: {١}",firstInt, secondInt );

// create a dog

Dog milo = new Dog( );

// assign a value to weight

milo.weight = ۵;

// create a second reference to the dog

Dog fido = milo;

// display their values

Console.WriteLine( "Milo: {٠}, fido: {١}",milo.weight, fido.weight );

// assign a new weight to the second reference

fido.weight = ٧;

// display the two values

Console.WriteLine( "Milo: {٠}, fido: {١}",milo.weight, fido.weight );

}

static void Main( )

{

Tester t = new Tester( );

t.Run( );

}

}

}

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

firstInt: ۵ secondInt: ۵

firstInt: ۵ secondInt: ٧

Milo: ۵, fido: ۵

Milo: ٧, fido: ٧

را ایجاد و secondInt و مقداردهی آن به 5 آغاز میشود. متغیر دوم بنام firstInt برنامه با ایجاد یک متغیر صحیح بنام

مقداردهی میکند. مقادیر آنها در خروجی به صورت زیر نمایش داده میشوند: firstInt با

firstInt: ۵ secondInt: ۵

2- شکل 5

ساخته و به firstInt یک نوع دادهی مقداری است که یک کپی از مقدار int این مقادیر یکسان هستند. چون

یک متغیر مستقل است. secondInt 2 نشان میدهد، متغیر - انتساب میدهد. همانطور که شکل 5 secondInt

انتساب میدهد . secondInt سپس برنامه یک مقدار جدید به

secondInt = ٧;

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

تغییر داده میشود.

3- شکل 5

فصل چهار-برنامه نویسی شی گرا

103

زمانی که دادهها نمایش داده میشوند، مقادیر آنها متفاوت هستند.

firstInt: ۵ secondInt: ٧

بوده و هر متد از هر public است. این فیلد weight با فقط یک فیلد بنام Dog گام بعدی ایجاد یک کلاس ساده بنام

ذخیره میکنید. milo را معرفی کرده و یک ارجاع به آن در Dog کلاسی میتواند به آن دسترسی داشته باشد. شما یک شی

Dog milo = new Dog( );

انتساب دهید. milo مقدار 5 را به فیلد وزن

milo.weight = ۵;

به milo که heap مقدار 5 قرار داده شده است. اما در واقع وزن شی بدون نام روی milo بطور معمول گفته میشود، وزن

4 نشان داده شده است . - آن ارجاع میکند مقداردهی شده است. همانطور که در شکل 5

4- شکل 5

مقداردهی کنید. این عمل ارجاع جدیدی به آن شی روی milo ایجاد کرده و آنرا با Dog در گام بعدی ارجاع دیگری به

ایجاد میکند. heap

Dog fido = milo;

و مقدار دهی اولیه آن میباشد secondInt توجه کنید که قانون ایجاد این متغیر و مقداردهی اولیهی آن، شبیه ایجاد متغیر

int secondInt = firstInt;

Dog fido = milo;

نیست. آن یک ارجاع به همان شی milo یک کپی از fido یک نوع دادهی ارجاعی است، پس Dog با این تفاوت که چون

وجود Heap 5 میبینید، در حال حاضر یک شئ با دو ارجاعکننده به آن روی - است. پس همانطور که در شکل 5 milo

را تغییر میدهید . fido دارد. زمانی که وزن شی

fido.weight = ٧;

نیز تغییر مییابد و خروجی زیر منعکس میگردد. milo وزن شی مربوط به

Milo : 7, Fido : 7

milo را تغییر میدهد. پس بطور همزمان مقدار شی Heap را تغییر نمیدهد. آن شی بدون نام روی milo شی ،fido شیء

نیز تغییر مییابد.

Mohsen_mahyar@yahoo.com - C# برنامه نویسی

104

ایجاد Heap روی Dog را بکار ببرید، یک نمونهی جدید از new کلمه کلیدی fido توجه: اگر زمان ایجاد

به شی یکسانی اشاره نمیکنند. milo و fido میکنید و

5- شکل 5

اگر کلاسی نیاز دارید که شبیه نوع داده مقداری رفتار کند، بایستی ساختار 1 ایجاد کنید.

-9-5 خلاصه

، اعلان کرده و سپس متدها، فیلدها، نمایندهها 2 class • زمان تعریف یک کلاس جدید، نام کلاس را با کلمه کلیدی

رویدادها و خصوصیات آن را تعریف کنید.

new • برای معرفی یک شی، همانند یک متغیر محلی نام شی را به دنبال نام کلاس اعلان کنید. سپس کلمهی کلیدی

لازم دارید. Heap را برای تخصیص حافظه به آن شی روی

فراخوانی یک متد روی شی با نوشتن عملگر نقطه بعد از نام شی و نام متد و پارامترهای آن بعد از نقطه امکان پذیر

است.

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

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

نشانهگذاری شدهاند، هیچ محدودیتی ندارند و برای هر متد از هر کلاسی نمایان هستند. public • اعضایی که با

فقط به متدهای همان کلاس نمایان هستند. private • اعضای

به متدهای همان کلاس و متدهای کلاس مشتق شده از آن کلاس نمایان هستند. protected • اعضای

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

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

به نمونهی جاری یک شی اشاره this • زمان تعریف اعضای کلاس میتوانید به آنها مقدار اولیه دهید. کلمه کلیدی

میکند.

به هر متد غیرایستای یک کلاس ارسال میشود. this • یک متغیر صریح

1 Struct

2 Delegate

فصل چهار-برنامه نویسی شی گرا

105

اعضای ایستا به خود کلاس نه به نمونهی خاصی از آن کلاس انتساب داده میشوند. اعضای ایستا با کلمه کلیدی

را بکار نمیبرند، this اعلان میشوند و از طریق نام کلاس احضار میشوند. متدهای ایستا کلمه کلیدی static

چون هیچ نمونهای از کلاس وجود ندارد.

هر شی بدون استفاده را خراب میکند. GC به کمک .NET متد مخرب ضروری نیست، چون چارچوب #C • در

فراهم کنید. ()Dispose • اگر یک کلاس از منابع مدیریت نشده استفاده کند، باید یک متد

ایجاد میشوند. زمانی که متد پایان مییابد، این متغیرها از میدان خارج Stack • متغیرهای محلی نوع مقداری روی

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

ایجاد میشوند. زمان اعلان یک نمونه از نوع ارجاعی، در واقع یک Heap • اشیاء از نوع دادهی ارجاعی هستند و روی

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

نمانده باشد، آن شی به Heap متد، ارجاع مورد نظر خراب می شود.در صورتی که هیچ ارجاعی به آن شی روی

خراب میشود. GC وسیله

 

   + MOHSEN GHASEMI - ٩:٥٩ ‎ق.ظ ; ۱۳۸٩/٤/٥