تالار گفتمان نبض فردا  

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

اطلاع رسانی

ارسال موضوع جدید  پاسخ
 
ابزارهای موضوع نحوه نمایش
قدیمی 04-18-2012   #11
Mino
عضو تالار
 

تاریخ عضویت: Feb 2012
محل سکونت: خوزستان، اهواز،
نوشته ها: 802
تشکرهای ایشان: 22,059
33,363بار در12,628پست از ایشان تشكر شده است

صندوق مدال ها

پیش فرض

درس 7
جاوا عملگرهای operator غنی زیادی دارد و بیشتر این عملگر ها رو می تونیم تو ۴ دسته تقسیم کنیم: ۱- عملگرهای حسابیarithmetic ۲- عملگرهای بیتی bitwise 3- عملگرهای منطقی logical و ۴- عملگرهای رابطه ای relational . جاوا همچنین چند عملگر اضافی دارد که شرایط ویژه را مدیریت می کند. ما در این بخش تمامی عملگرها به جز عملگر instanceof رو که در بخش های آینده مطالعه میشه؛ عنوان خواهیم کرد.

نکته: اگر با زبانهای C/C++ آشنا هستید خوشحال باشید چون اکثر عملگرهای این زبانها مانند جاوا هستند البته با تفاوتهای اندک اما به طور خاص خواندن دقیق این فصل رو به شما توصیه میکنیم.

عملگرهای حسابی

این عملگرها به همان صورت که در جبر به کار می روند در جملات حسابی به کار برده خواهند شد. فهرست این عملگرها رو با هم می بینیم:
عملگر نتیجه
+ جمع
- تفریق
* ضرب
/ تقسیم
% باقیمانده تقسیم
++ افزایش
=+ جمع و تخصیص
=- تفریق و تخصیص
=* ضرب و تخصیص
=/ تقسیم و تخصیص
=% باقیمانده تقسیم و تخصیص
– کاهش


عملوندهای operand عملگرهای حسابی باید از نوع عددی باشند.آنها را نمی توانید همراه با داده های نوع Boolean به کار ببرید اما می توان آنها را برای داده های نوع char به کار ببرید چون char در جاوا اساسا زیرمجموعه ای ازint است.

عملگرهای حسابی پایه

عملیات حسابی پایه basic –جمع ؛تفریق ؛ ضرب ؛تقسیم- همانگونه ای عمل می کنند که برای داده های عددی انتظار دارید. عملگر “-” یک فرم یگانگی دارد که فقط عملوندش را منفی می کند. به خاطر داشته باشید که وقتی عملگر تقسیم(/) با داده های صحیح به کار برده می شود ؛ حاصل تقسیم فاقد بخش اعشاری خواهد بود.قطعه برنامه زیر عملکرد عملگرهای حسابی را نشان می دهدو تفاوت بین تقسیم اعداد صحیح و تقسیم اعداد اعشاری را بیان می کند:01 //demonstrate the basic arithmetic operators.
02 Class BasicMath{
03 Public static void main(string args[] )
04 //arithmetic using integers
05 System.out.println(“integer Arithmetic”);
06 Int a=1+1;
07 Int b=a*3;
08 Int c=b/4;
09 Int d=c-a;
10 Int e=-d;
11 System.out.println(“a=”+a);
12 System.out.println(“b=”+b);
13 System.out.println(“c=”+c);
14 System.out.println(“d=”+d);
15 System.out.println(“e=”+e);
16 //arithmetic using doubles
17 System.out .prinln(“\nFloating point Arithmetic”);
18 Double da=1+1;
19 Double db=da*3;
20 Double dc=db/4;
21 Double dd=dc-a;
22 Double de=-dd;
23 System.out.println(“da=”+da);
24 System.out.println(“db=”+db);
25 System.out.println(“dc=”+dc);
26 System.out.println(“dd=”+dd);
27 System.out.println(“de=”+de);
28 }
29 }


Out put:
Integer Arithmetic
A=2
B=6
C=1
D=-1
E=1
Floating point Arithmetic
Da=2.0
Db=6.0
Dc=1.5
Dd= -0.5
De=0.5

عملگر باقیمانده تقسیم
عملگر باقیمانده تقسیم؛ % باقیمانده تقسیم را بر می گرداند. این عملگر را می توان هم برای اعداد اعشاری با ممیز شناور و هم برای انواع داده های صحیح به کار برد. این قطعه برنامه عملکرد این برنامه را نشان می دهد:1 //demonstrate the % operator
2 Class modulus{
3 Public static void main(string args[]){
4 Int x=42;
5 Double y=42.25;
6 System.out.println(“x mod 10 =”+x%10);
7 System.out.println(“y mod 10=” +y%10);
8 }
9 }


Out put:
X mod 10 =2
Y mod 10 =2.25

عملگر های تخصیص
جاوا عملگرهای ویژه ای دارد که با استفاده از آنها می توان یک عمل حسابی را با عمل تخصیص ترکیب نمود. عباراتی چون عبارت زیر در برنامه سازی متداولند:1 A=a+4;
2 A +=4 ;


در عبارت بالا از عملگر”=+” استفاده شده است. عملکرد هر دو عبارت یکسان است: مقدارa را به اندازه ۴ واحد افزایش می دهند.
عملگرهای تخصیص برای تمام عملگرهای حسابی باینری موجودند. از این رو هر عبارت به شکل زیر1 Var = var op expression;


را می توان به این صورت بازنویسی کرد:1 Var op=expression;


عملگرهای تخصیص دو فایده دارند.نخست اینکه در حجم کار تایپ قدری صرفه جویی می شود؛ چرا که “فرم کوتاه” معادل خود هستند. دوم اینکه پیاده سازی آنها در سیستم زمان اجرای جاوا ؛ کارآمدتر از معادلشان است. به خاطر این دلایل اغلب این عملگرها را برنامه های حرفه ای جاوا خواهید دید.

افزایش و کاهش
“++” و”- -” عملگرهای افزایش و کاهش جاوا هستند.این عملگرها چند خصوصیت ویژه دارند که آنها را کاملا جذاب کرده اند.. بحث خود را با مرور دقیق عملکرد این دو عملگر آغاز می کنیم:
عملگر افزایش ؛ یک واحد به عملوند خود می افزاید و عملگر کاهش نیز یک واحد از عملوند خود می کاهد برای مثال:1 X=x+1 ;


این عبارت را می توان به این صورت نیز نوشت:1 X ++ ;


برای کاهش نیز دقیقا می توان از عبارت x- -; به جای x=x – ۱; استفاده کرد.این عملگرها از این جهت می توانند به صورتpostfix (عملگر پس از عملوند قرار گیرد) و همینطور prefix(عملگر پیش از عملوند قرار گیرد) باشند؛ منحصر به فرد است. در جملاتی که دکر شد هیچ فرقی بین جملات postfix و prefix وجود ندارد اما وقتی از این عملگرها در بخشی از یک عبارت جبری استفاده کنیم؛ تفاوتهایی جزیی ولی بسیار تاثیر گذار به وجود می آید.
در جملات جبری در فرم postfix پیش از آنکه از مقدار متغیر در جمله استفاده شود عملوند افزایش یا کاهش می یابد و در فرم prefix مقدار در جملات جبری به کار می رود و پس از آن عمل افزایش یا کاهش روی آن انجام می شود.
مسئله خیلی ساده ای است ولی اگر به آن بی توجه ای شود نتیجه جمله جبری شما با ۱۸۰ درجه اختلاف نمایان می شود.
(راستش خودم هم از عنوان این بحث ها خسته شدم چون توC++ هم دقیقا همین مطالب رو داشتیم اما وظیفه حکم میکند برای دوستانی که جاوا زبان اول آنها برای آموزش است ؛ مطالب رو دقیق عنوان کنم)

عملگرهای بیتی
جاوا چندین عملگر بیتی دارد که می توان با انواع داده های صحیحlong,int,short,char و byte به کار برد. این عملگرها بر روی یکایک بیت های عملوند خود عمل می کنند. فهرست این عملگرها را در جدول خواهیم دید:
عملگر نتیجه
- Not یکانی بیتی
& And بیتی
| Or بیتی
^ Xor بیتی
>> شیفت به راست
>>> شیفت به راست با صفر اضافی
<< شیفت به چپ
&= And بیتی و تخصیص
!= Or بیتی و تخصیص
^= Xor بیتی و تخصیص
>>= شیفت به راست و تخصیص
>>>= شیفت به راست و تخصیص با صفر اضافی
<<= شیفت به چپ و تخصیص


از آنجایی که عملگرهای بیتی ؛ بیت های اعداد صحیح را پردازش و مدیریت می کنند؛ مهم است که با تاثیر این چنین پردازشها بر روی مقادیر آشنا باشیم.

بخصوص اینکه دانستن اینکه جاوا چطور مقادیر صحیح را ذخیره می کند و چکونه اعداد منفی را نمایش می دهد؛ مفید خواهد بود بنابراین این دو موضوع را شرح خواهیم داد.

تمام اعداد صحیح به وسیله اعداد باینری به طول متغیر نمایش داده می شوند. مثلا مقدار ۸۴ نوع byte ؛۰۰۱۰۱۰۱۰ است که ارزش مکانی هر رقم؛ توانی از ۲ است. ارزش مکانی سمت راست ترین بیت؛ ۲۰ است. ارزش مکانی بیت سمت چپ آن ۲۱ یا ۲ است و این عملیات به همین صورت ادامه خواهد یافت پس برای مثال در مورد عدد صفر و یک بالا این عملیات را برای تبدیل آن از حالت باینری به دسیمال انجام خواهیم داد:

۰*۲۰+۰*۲۱+۱*۲۲+۰*۲۳+۱*۲۴+۰*۲۵+۱ *۲۶+۰*۲۷=۰+۰+۴+۰+۱۶+۰+۶۴=۸۴

انواع داده های صحیح ؛ (به غیر از char ) اعداد صحیح علامت دار هستند یعنی نمایانگر مقادیر مثبت و منفی هستند. جاوا از نوعی روش رمز گذاری به نام”مکمل ۲ ” استفاده می کند که در آن اعداد منفی از طریق معکوس کردن تمام بیت ها( تبدیل یک ها به صفر و بالعکس) و سپس افزودن یک واحد به حاصل ؛ نمایش داده می شوند. برای مثال ۸۴- با معکوس کردن تمام بیت های عدد ۸۴ (یا ۰۰۱۰۱۰۱۰) که نتیجه اش ۱۱۰۱۰۱۰۱ است و سپس افزودن یک واحد به آن نمایش داده می شود(یعنی ۱۱۰۱۰۱۱۰). برای رمزگشایی هر عدد منفی نخست تمام بیت ها را معکوس کنید و سپس یک واحد به نتیجه آن بیفزایید.
چنانچه مسئله “zero crossing” را در نظر بگیرید درک دلیل استفاده جاوا(و اکثر زبانهای دیگر)از مکمل ۲ آسان می شود. با فرض اینکه صفر از نوع byte است؛ نمایش باینری آن به صورت۰۰۰۰۰۰۰۰ می شود . در روش مکمل ۱ نتیجه معکوس کردن بیت ها؛ ۱۱۱۱۱۱۱۱است که نمایانگر صر منفی است. مشکل اینجاست که صفر منفی در ریاضیات بی مفهوم است. این مشکل با استفاده از مکمل ۲ برای نمایش مقادیر منفی حل می شود. وقتی از مکمل ۲ استفاده می کنید یک واحد به نتیجه معکوس شده اضافه می گردد که نتیجه آن۱۰۰۰۰۰۰۰۰ می شود. این کار سبس یک شدن بیت منتهی الیه سمت چپ می شود که در داده های نوع بایت جایی نخواهد داشت و بنابراین رفتار مورد نظر حاصل شده و ۰- همان ۰ استو ۱۱۱۱۱۱۱۱ مقدار رمزگذاری شده ۱- خواهد بود.
Mino آنلاین نیست.   پاسخ با نقل قول
Sponsored Links
قدیمی 04-18-2012   #12
Mino
عضو تالار
 

تاریخ عضویت: Feb 2012
محل سکونت: خوزستان، اهواز،
نوشته ها: 802
تشکرهای ایشان: 22,059
33,363بار در12,628پست از ایشان تشكر شده است

صندوق مدال ها

پیش فرض

بقیه درس 7
عملگرهای منطقی بیتی
این عملگرها را در جدول زیر خواهید دید:
-A
A^B
A&B
A|B
B
A

1
0
0
0
0
0

0
1
0
1
0
1

1
1
0
1
1
0

0
0
1
1
1
1


NOT بیتی


عملگر یگانی (~)NOT1 که مکمل بیتیbitwise complement نیز نامیده می شود؛تمام بیت های عملوند خود را معکوس می کند.

AND بیتی

چنانچه هر دو طرف عملوند عملگر AND(&) یک باشد؛ حاصل نیز یک خواهد بود در غیر این صورت در تمام حالات دیگر؛ صفر است.

OR بیتی

عملگر OR(|) اگر تنها یکی از عملوند هایش یک باشد؛ حاصل یک خواهد داشت در غیر این صورت صفر است.

XOR بیتی

عملگر XOR(^) در صورتی که عملوند هایش هر دو مشابه باشند مثلا هر دو صفر یا هر دو یک باشند حاصل صفر را نمایش می دهد و اگر متفاوت باشند حاصل یک را نمایش خواهد داد.

شیفت به چپ

عملگر شیفت به چپ(<<) تمام بیت های عملوندش را به اندازه تعداد دفعات مشخص شده به سمت چپ انتقال می دهد. برای درک بهتر با یک مثال توضیح می دهم:

عدد مورد نظر: ۶۴

تبدیل عدد از حالت دسیمال به باینری: ۰۰۰۰۰۰۰۱

۰۰۰۰۰۰۰۱<<2

یعنی می خواهیم حالت باینری عدد ۶۴ را۲ بار به چپ shift یا انتقال بدهیم:

۰۱۰۰۰۰۰۰

۱۰۰۰۰۰۰۰

وقتی مقادیر نوع byte وshort را شیفت می دهید؛ عمل ارتقاء خودکار جاوا منجر به تولید نتایج غیر منتظره می شود. همانگونه که می دانید؛ وقتی یک جمله جبری ارزیابی می شود؛ مقادیر نوع byte و short به نوعint ارتقاء می یابند.علاوه بر آن نتیجه یک چنین جمله ای نیزint خواهد شد. این بدین معناست که نتیجه شیفت به چپ در مقادیر byteو short ؛int می شودو بیت های شیفت شده هم تازمانی که از موقعیت ۳۱ ام نگذرند؛ از دست نمی روند.چون نتیجه هر شیفت چپ؛ دو برابر شدن مقدار اولیه است .برنامه سازان از این امر به عنوان یک جایگزین کارآمدتر برای ضرب در ۲ استفاده می کنند.

شیفت به راست

عملگر شیفت به راست(>>) تمام بیت های عملوندش را به اندازه تعداد دفعات مشخص شده به راست انتقال می دهد.وقتی مقداری را به راست شیفت می دهیم؛ آن مقدار بر ۲ تقسیم می شود و باقیمانده نادیده انگاشته می شود.

عملگر بیتی و تخصیص

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

A=a>>4 ;
a>>= 4 ;
a=a|b ;
a|=b ;

عملگر های رابطه ای

عملگر های رابطه ای relational رابطه یک عملوند را نسبت به یک عملوند دیگرش مشخص می کند. این عملگرها تساوی و ترتیب عملوند ها را تعیین می کند:عملگر نتیجه
== مساوی است با
=! مخالف است با
> بزرگتر از
< کوچکتر از
>= بزرگتر یا مساوی با
<= کوچکتر یا مساوی با


نتیجه این عملیات یک مقدار بولی است. عملگر های رابطه ای بیشتر در جملات جبری که عبارت if را کنترل می کنند و همین طور در حلقه های گوناگون به کار برده می شود.

اگر تجربه کار با C/C++ را دارید؛ لطفا به نکته زیر دقت کنید. انواع عبارات زیر در C/C++ بسیار متداولند:
1 Int done;
2 //…
3 If(!done) … //valid in C/C++
4 If(done) … // but not in java.


عبارت بالا در جاوا اینگونه نوشته می شود:
1 If(done==0)… //this is java style.
2 If(done != 0) … //


دلیل این امر آن است که تعریفtrue و false در جاوا همچون C/C++ نیست.true در C/C++ ؛ هر مقدار مخالف صفر است و false نشانگر مقدار صفر. True و false در جاوا مقادیر غیر عددی هستند که ارتباطی با صفر و غیر صفر ندارند. بنابراین برای مقایسه با صفر و غیر صفر؛ باید از یک یا چند عملگر رابطه ای استفاده کنید.

عملگرهای منطقی بیتی

این عملوند ها تنها برای نوع Boolean قابل استفاده هستند. تمام عملگرهای منطقی بولی دو مفدار نوع Boolean را با هم ترکیب می کنند تا نتیجه یک مقدار نوعboolean شود.
عملگر نتیجه
& ANDمنطقی
| OR منطقی
^ XOR منطقی
|| OR اتصال کوتاه
&& AND اتصال کوتاه
! NOT یگانی منطقی
&= AND و تخصیص
|= OR و تخصیص
^= XOR و تخصیص
== مساوی است با
!= مخالف است با
?: If-then-else سه تایی


عملکرد عملگرهای بولی منطقی(&,|,^) بر روی مقادیر بولی همچون عملکردشان بر روی بیت های یک عدد صحیح است. عملگر منطقی “!” وضعیت بولی را معکوس می کند: !true=false و !false=true نتایج را در جدول زیر می بینیم:
!A
A^B
A&B
A|B
B
A

true
false
false
false
false
False

false
true
false
true
false
True

true
true
false
true
true
False

false
false
true
true
true
true


عملگرهای منطقی اتصال کوتاه

جاوا دو عملگر بولی جالب دارد که در بسیاری از زبانهای کامپیوتری دیگر وجود ندارد. این عملگر ها؛ نگارشهای ثانویه دو عملگر AND و OR بولی هستند و تحت عنوان عملگرهای منطقی”اتصال کوتاه” short-circuit شناخته شده اند. همانگونه که از جدول قسمت قبل مشخص است؛ نتیجه عملگر OR زمانی true است کهA مقدارشtrue باشد؛ صرفنظراز مقدارB .همین طور حاصل عملگر AND زمانیfalse است کهA مقدارش false باشد؛ صرفنظر از مقدارB .اگر به جای فرم های | و & این عملگرها از دو فرم || و&& استفاده کنید؛ در آن صورت چنانچه جاوا بتواند نتیجه جمله شرطی را تنها به وسیله عملوند سمت چپ تعیین کنید؛ در آن صورت دیگر عملوند سمت راست را ارزیابی نخواهد کرد. این امر برای مواقعی که عملوند سمت راستtrue یا false بودن عملوند سمت چپ وابسته باشد؛ بسیار مفید است. در مثال زیر نشان می دهیم چگونه با استفاده از ارزیابی منطقی اتصال کوتاه می توانید پیش از یک عمل تقسیم اطمینان حاصل کنید که حاصل آن درست خواهد بود یا خیر:1 If (denom != 0 && num/ denom >10)


چون از فرم اتصال کوتاه AND (&&) استفاده شده است؛ احتمال بروز استثنایexception “زمان-اجر” به دلیل صفر بودن denom از بین می رود. اگر این سطر با استفاده از نگارش & عملگر AND نوشته شود؛ می بایست هر دو طرف عملگر منطقی ارزیابی می شد و در نتیجه استثنای”زمان –اجرا” در صورت صفر بودن denom پیش می آمد.
خوب است در مواقعی که با منطق بولی سروکار دارید از فرم های اتصال کوتاهAND وOR استفاده کنید و نگارشهای تک نمادی را صرفا برای عملیات بیتی باقی بگذارید. اما این قانون استثنا هم دارد. عبارت زیر را در نظر بگیرید:1 If (c==1 & e++ <100) d=100;


استفاده از& در اینجا تضمین می کند که افزایش مقدار e صرفنظر از یک بودن مقدارc انجام می شود.

عملگر تخصیص
عملگر تخصیص با علامت “=” نشان داده می شود. عملکرد عملگر تخصیص در جاوا همچون سایر زبانهای کامپیوتری است.1 Var = expression ;


نوع داده var باید به نوع expression سازگار باشد.
عملگر تخصیص ویژگی جالبی دارد که شاید با آن آشنا نباشید. امکان ایجاد زنجیره ای از عملیات تخصیص را فراهم می سازد. به عبارت زیر توجه کنید:1 Int x,y,z ;
2 X=y=z=100; // set x,y,z to 100


دلیل میسر بودن اید ویژگی آن است که “=” عملگری است که نتیجه آن ؛ سمت راست عبارت است. از این رو مقدار z=100 ؛ ۱۰۰ است که به y تخصیص می یابد و آن نیز به نوبه خود به x تخصیص می یابد. استفاده از زنجیره تخصیص روش آسانی برای نسبت دادن یک مقدار مشترک به گروهی از متغیر ها ست.

عملگر ?
جاوا نوعی عملگر سه تایی ternary ویژه دارد که می تواند جانشین برخی از انواع خاص عبارتهای if-then-else شود. این عملگر؛ “?” است. ممکن است در نگاه اول این عملگر گیج کننده به نطر بیاید اما پس از تسلط یافتن بر آن می توانید به شکل موثری از آن استفاده کنیدو شکل کلی این عملگر به این صورت است:1 Expression 1 ? expression2: expression 3


Expression1 میتواند هر جمله ای با حاصل نوعboolean باشد. اگر حاصل آن true باشد در آن صورت expression2 ارزیابی می شود در غیر این صورت expression3 ارزیابس می شود. نتیجه عملگر ? همان نتیجه ارزیابی جملات آن است. حاصل هر دو جملهexpression2 وexpression3 باید از یک نوع باشذ و نمی تواند void باشد. قطعه برنامه زیر کاربرد عملگر”?” را نشان می دهد.برنامه از این عملگر برای به دست آوردن قدر مطلق یک متغیر استفاده می کند:
01 //demonstrate ?.
02 Class Ternary{
03 Public static void main(string args[]) {
04 Int I,k ;
05 I=10;
06 K=i<0 ? –I : I ; //get absolute value of I
07 System.out.print(“Absolute value of “ );
08 System.out.println(i+”is”+k);
09 I=-10;
10 K=i<0?-i:I //get absolute value of i
11 System.out.print(“Absolute value of”);
12 System.out.println(i+”is”+k);
13 }
14 }


Out put:
Absolute value of 10 is 10
Absolute value of-10 is 10

تقدم عملگرها

جدول زیر ترتیب اولویت ها را نشان می دهد. سطر اول شامل عملگرهایی است که عموما به آنها توجه نمی کنیم. عملگرهایی مانند (),[],(.) این موارد را جداساز می نامیم اما عملکرد آنها در جملات جبری همچون عملگرهاست. پرانتز ها برای تغیر تقدم یک عمل به کار برده می شود.[] برای امکان مشخص کردن ایندکس آرایه به کار می رود و (.) برای

ارجاع به شی ء ها استفاده می شود.بالاترین
() []
++ – ~ ~
* / %
+ -
>> >>> <<
> => < <=
== !=
&
^
|
&&
||
?:
= Op=
پایین ترین


کاربرد پرانتز ها

پرانتز ها ؛ تقدم عملیات مندرج در بین خود را افزایش می دهد. این کار اغلب برای به دست آوردن نتیجه مورد نظر ضروری است.

a>>b+3

در جمله بالا ابتدا ۳ واحد به b افزوده می شود و سپسa به اندازه نتیجه حاصل به سمت راست شیفت داده می شود. این جمله را می توان با استفاده از پرانتزهای اضافی به صورت زیر بازنویسی کرد:

a>>(b+3)

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

(a>>b)+3

پرانتز ها علاوه بر تغییر تقدم معمول یک عبارت؛ گاهی برای کمک به شفاف کردن مفهوم جملات جبری به کار برده می شوند.
یک نکته دیگر: پرانتز ها در کل موجب کاهش کارایی برنامه تان نمی شوند بنابراین افزودن پرانتز ها برای کاهش ابهام برنامه ها؛ تاثیر منفی بر آنها نخواهد داشت.
Mino آنلاین نیست.   پاسخ با نقل قول
قدیمی 04-18-2012   #13
Mino
عضو تالار
 

تاریخ عضویت: Feb 2012
محل سکونت: خوزستان، اهواز،
نوشته ها: 802
تشکرهای ایشان: 22,059
33,363بار در12,628پست از ایشان تشكر شده است

صندوق مدال ها

پیش فرض

درس 8
عبارات کنترلی: هر زبان برنامه سازی از عبارات کنترلی برای هدایت جریان اجرای برنامه بر اساس تغیییرات وضعیت آن استفاده می کند. عبارات کنترلی جاوا به دو دسته تقسیم می شوند: ۱- انتخاب ۲- تکرار و۳- پرش. عبارات انتخابselection statement به برنامه ها امکان می دهد تا مسیر های اجرایی مختلفی را بر اساس نتیجه یک جمله جبری یا وضعیت یک متغیر؛انتخاب کند. عبارات کنترلiteration statement به برنامه ها امکان می دهد تا یک یا چند عبارت را تکرار کند(ایجاد حلقه ها) و عبارات پرشjump statement به برنامه ها امکان می دهد تا به صورت غیر خطیnonlinear اجرا شوند.

نکته: اگر با C/C++/C# آشنا باشید این فصل به نظر شما بسیار آسان خواهد آمد. در واقع عبارات کنترلی جاوا بسیار شبیه به زبانهای مذکور است اما چند تفاوت نیز به ویژه در مورد دستوراتbreak و continue وجود دارد.

عبارات انتخاب جاوا

جاوا از دو نوع عبارت انتخاب پشتیبانی می کند: if وswitch . این عبارات امکان کنترل جریان اجرای برنامه ها را بر اساس شرایطی که تنها در طی اجرای مشخص می شوند؛ فراهم می سازد. این دو عبارت قدرت و انعطاف پذیری شگفت انگیزی دارند.

If

عبارت if ؛عبارت انشعاب شرطی جاواست.با استفاده از آن می توان اجرای برنامه ها را از طریق دو مسیر مختلف هدایت نمود. با شکل کلی این عبارت آشنا می شویم:1 If (condition) statement 1 ;
2 Else statement 2 ;


Statement در هر یک از دو حالت می تواند یک عبارت واحد یا چند عبارت در بین {} brace باشد(یعنی یک block ). Condition نیز می تواند هر شرطی با حاصل Boolean باشد. قسمتelse هم اختیاری است.

عبارت if به این شرح است: اگر حاصل condition مقدار true باشد در آن صورتstatement 1 اجرا می شود و در غیر این صورت؛ statement 2 (در صورت وجود) اجرا می گردد. تحت هیچ شرایطی دو عبارت با هم اجرا نمی شود.

در بیشتر مواقع در شرط کنترلif از عملگرهای رابطه ای استفاده می شود اما این امر از نظر فنی ضرورت ندارد. عبارتif را می توان همچون مثال زیر با یک مقدار بولی هم کنترل کرد:
1 Boolean dataAvailable;
2 //…
3 If (dataAvailable)
4 processData() ;
5 else
6 waitForMoreData();


if های تو در تو(متداخل)


منظور از if تودرتو آن است که عبارتif دیگری؛ در یک if یا else دیگر قرار گیرد. Ifهای تودرتو در برنامه سازی بسیار متداول هستند. مهمترین نکته در مورد این نوعifها این است که باید به خاطر داشته باشید که هر عبارتelse همیشه به نزدیکترین عبارتif موجود در همان بلوکelse که باelse دیگری هم مرتبط نیست؛ ارجاع دارد.
1 {If (i==10)
2 If(j<20) a=b;
3 If(k>1000) c=d;
4 Else a=c;
5 }
6 Else a=d;


نردبان if-else-if

یکی از ساختارهای برنامه سازی متداولی که بر اساس یک سری ifهای تودرتو بنا شده است؛ نردبانladder ؛if-eelse-if است که به صورت زیر نوشته می شود:
01 If (condition)
02 Statement;
03 Else if (condition)
04 Statement;
05 Else if(condition)
06 Statement;
07 .
08 .
09 .
10 Else
11 Statement;


عبارات if از بالا به پایین اجرا می شوند .به محض اینکه حاصل یکی از شرطهای کنترل کننده if مقدار true باشد؛ عبارت مرتبط با آن if اجرا شده و از مابقی نردبان صرفنظر می شود.اگر هیچ یک از شرطها درست نباشد؛ آخرین عبارت else اجرا خواهد شد. آخرین else به صورت پیش فرض عمل می کند یعنی چنانچه هیچ یک از شرطها برقرار نباشد ؛ در آن صورت آخرین عبارت else اجرا می شود و اگر عبارتelse آخری موجود نباشد و مقدار تمام شرطها نیزfalse باشد در آن صورت هیچ عملی انجام نمی گیرد.

Switch
عبارتswitch عبارت انشعاب چند شاخه ای جاوا است. این عبارت روش آسانی برای هدایت کنترل اجرای برنامه به قسمتهای مختلف بر اساس مقدار یک جمله جبری فراهم می سازد. بدین ترتیب؛جایگزین بهتری برای یک سری عبارات if-else-if طولانی به شمار می آید:
01 Switch (expression) {
02 Case value 1:
03 //statement sequence
04 Break;
05 Case value 2:
06 //statement sequence
07 Break;
08 .
09 .
10 .
11 Case value N:
12 Break;
13 Default:
14 //default statement sequence
15 }


Expression باید از نوع byte,short ,int یا char باشد. هر یک ازvalue های مشخص شده در عبارات case باید از نظر نوع متناسب با expression باشند.(از مقادیر نوع enumeration که در آینده بررسی می شوند می توان برای کنترل switch استفاده نمود)
هر یک از مقادیرcase باید یک لیترال منحصر به فرد باشد(باید یک مقدار ثابت باشد و نه متغیر).مقدار case نباید تکراری باشد.
عملکردswitch به این شرح است:
مقدارexpression با هریک از مقادیر لیترال عبارت case مقایسه می شود. اگر مقدار متناظری پیدا شود؛ عبارت یا عبارتهای پس از case اجرا می شود. اگر هیچ یک از مقادیر ثابت با مقدار expression برابر نباشد؛ در آن صورت عبارتdefault اجرا می شود. با این وجود عبارت مذبور اختیاری است. اگر مقدار متناظری پیدا نشود و عبارت default هم موجود نباشد در آن صورت هیچ عملی انجام نمی شود.
از عبارتbreak درswitch برای پایان دادن به یک سری از عبارات استفاده می شود. وقتی نوبت به اجرای عبارتbreak می رسد؛ اجرای برنامه به نخستین سطر پس از کل عبارت switch هدایت می شود. بدین ترتیب کنترل از عبارت switch خارج می شود.
حذف عبارتbreak کاربردهای عملی زیادی در برنامه های واقعی دارد.

عبارات switch تو در تو

از عبارتswitch می توانید به عنوان یکی از عبارات یک switch دیگر استفاده کنید. ار آنجایی که هر عبارتswitch بلوک مخصوص به خود را تعریف می کند؛ هیچ تداخلی بین ثابت case های switch داخلی و خارجی پیش نمی آید.

سه ویژگی مهم و قابل توجه از عبارتswitch به طور خلاصه در ذیل فهرست شده اند:
عبارت switch بر خلاف عبارتif تنها قابلیت بررسی تساوی دو مقدار را دارد؛ در صورتی که if ها می توانندهر نوع جمله بولی را ارزیابی کنند. یعنی switch تنها مقداری را جستجو می کند که با یکی از ثابتهای case خود برابر باشد.
هیچکدام از ثابتهایcase در یک عبارتswitch نمی توانند با هم یکسان باشند.البته ثابتهای case یک عبارتswitch و عبارت switch داخل ن می توانند یکسان باشند.آآن می توانند یکسان باشند.
عبارتswitch معمولا کارآمد تر از مجموعه ای ازif های تودرتو است.

Mino آنلاین نیست.   پاسخ با نقل قول
قدیمی 04-18-2012   #14
Mino
عضو تالار
 

تاریخ عضویت: Feb 2012
محل سکونت: خوزستان، اهواز،
نوشته ها: 802
تشکرهای ایشان: 22,059
33,363بار در12,628پست از ایشان تشكر شده است

صندوق مدال ها

پیش فرض

بفیه درس 8


عبارات تکرار

عبارات تکرارiteration statement در جاوا عبارتند ازfor,while و do-while . نتیجه عملکرد این عبارات عموما حلقه loop نامیده می شود. هر حلقه مکررا مجموعه ای از دستورالعمل ها را آنقدر اجرا می کند تا شرط پایان کار برآورده شود. جاوا حلقه هایی برای برآورده ساختن تمام نیازهای برنامه سازی دارد.

While

حلقه while اصلی ترین حلقه جاوا محسوب می شود. تا زمانی که حاصل جمله کنترل کننده این حلقهtrue است؛ اجزای عبارت یا بلوکی از عبارات تکرار می شود. شکل کلی آن بدین صورت است:
1 While (condition) {
2 //body of loop
3 }


Condition می تواند هر جمله بولی باشد. تا زمانی که حاصل آن true باشد؛ قسمتbody اجرا می شود. هرگاه حاصل آن false شود؛ کنترل به نخستین سطر پس از حلقه هدایت می شود. چنانچه هدف تکرار ؛اجرای تنها یک عبارت باشد؛ وجود {} لازم نخواهد بود.
از آنجایی گه حلقه while جمله شرطی خود را در ابتدای حلقه بررسی می کند ؛ در صورت false بودن شرط؛ قسمت body حلقه اصلا اجرا نمی شود.
قسمت body حلقه while (یا سایر حلقه های جاوا) می تواند خالی باشد. دلیل این امر آن است که عبارتهایnull( عباراتی که تنها از یک” ; “ تشکیل می شوند)از نظر گرامری درست هستند.

Do – While

همانگونه که خواندید؛ چنانچه جمله شرطی کنترل کننده هر حلقه while از ابتدا false باشد؛ در آن صورت قسمت body حلقه اصلا اجرا نمی شود. اما گاهی لازم است قسمتbody حداقل یک مرتبه اجرا شود حتی اگر حاصل جمله شرطی از همان ابتدا false باشد. یعنی گاهی اوقات لازم است جمله شرطی را به جای ابتدا؛ در انتهای حلقه بررسی کنید.حلقهdo-while همیشه قسمتbody را حداقل یک مرتبه اجرا می کند ؛چرا که جمله شرطی آن در انتهای حلقه قرار دارد.شکل کلی آن را با هم می بینیم:1 Do {
2 //body of loop
3 }while (condition);


هر بار که حلقه do-while تکرار می شود؛ ابتدا قسمتbody اجرا می شود و سپس حاصل جمله شرطی ارزیابی می گردد. اگر این حاصلtrue باشد؛حلقه تکرار خواهد شد و در غیر این صورت حلقه به پایان می رسد. شرطه حلقه باید حتما از نوع Boolean باشد.
حلقه do-while خصوصا زمانی مفید است که از آن برای پردازش گزینه های یک منو استفاده می کنید. چرا که معمولا در این گونه شرایط لازم است قسمتbody حداقل یک مرتبه اجرا شود.

For
حلقهfor یکی از ساختارهای قدرتمند و کاربردی جاوا به شمار می آید.
وجود دو شکل مختلف برای حلقه for از نگارش J2SE 5 مطرح شد. نخستین شکل حلقه for ؛همان حلقه قدیمی است که از زمان عرضه نخستین نگارش جاوا مطرح بوده است. شکل دوم که شکل جدید این حلقه است؛ به صورتfor-each می باشد.
شکل کلی حلقه قدیمی به این صورت است:1 For ( initialization ; condition ; iteration) {
2 //body
3 }


حلقه for به این شکل عمل می کند:
وقتی حلقه آغاز می شود؛قسمت initialization حلقه اجرا می شود. عموما این قسمت جمله جبری است که مقدارد متغیر کنترل حلقه را تعیین می کند. از این متغیر به عنوان شمارنده کنترل حلقه استفاده می شود. لازم است بدانید که جمله جبری مقدار دهی اولیه تنها یک مرتبه اجرا می شود. سپس condition ارزیابی می شود. حاصل آن باید از نوع Boolean باشد.condition معمولا متغیر کنترل حلقه را با یک مقدار معین مقایسه می کند. چنانچه حاصل کار true باشد؛ قسمت body اجرا می شود.
چنانچه حاصل false باشد حلقه به پایان می رسد. سپس قسمتiteration حلقه اجرا می گردد .این قسمت معمولا جمله جبری است که مقدار متغیر کنترل حلقه را افزایش یا کاهش می دهد. حلقه سپس تکرار می شود و هر بار ابتدا جمله شرطی ارزیابی می شود؛سپس قسمت body اجرا می گردد و سپس قسمت interation اجرا می گردد. این فرآیند آنقدر تکرار می گردد تا حاصل جمله کنترل کنندهfalse شود.
گاهی اوقات لازم می شود که بیش از یک عبارت را در قسمتهایinitialization و interation به کار ببرید.برای این کار این عبارت ها را توسط کاما از هم جدا می کنیم.
می توانید سه قسمت نامبرده در حلقه for را حذف کنید؛ در این حالت می توانید یک حلقه نامحدود که هیچگاه به پایان نمی رسد بسازید.
هر کدام از این سه قسمت می تواند از ساختار اصلی حلقه for حذف گردد.

شکل for-each از حلقه for

نظریه معاصر زبانها مفهومfor-each را به خوبی پذیرفته است و این سبک به سرعت به یکی از ویژگه های استانداردی مبدل می شود که برنامه سازان می بایست انتظار آن را داشته باشند. حلقه سبک for-each به گونه ای طراحی شده است تا چرخه ای برای کلکسیونی از شی ء ها ؛مثلا یک آرایه؛ به صورت کاملا متوالی و سریال و از ابتدا تا انتها ایجاد نماید.
بر خلاف زبانهایی چون C# که این سبک از حلقه for را با استفاده از کلمه کلیدیforeach پیاده سازی می کنند؛ جاوا این قابلیت را از طریق بهبود عبارتfor افزوده است. مزیت این رویه آن است که کلمه کلیدی جدیدی لازم نیست و روتین های موجود نیز تغییر نمی یابند. به سبک for-each حلقه for ؛حلقه for پیشرفته نیز گفته می شود. شکل کلی حلقه را با هم می بینیم:1 For (type itr-var : collection) statement-block


type مشخص کننده نوع و itr-var مشخص کننده نام متغیر تکرار است که عناصر یک کلکسیون را یک به یک و از ابتدا به انتها دریافت می کند. کلکسیونی که چرخه برای آن ایجاد می شود؛ با collection مشخص می شود. انواع گوناگونی از کلکسیون ها را می توان با for به کار برد اما تنها نوع مورد استفاده در این unit ؛ آرایه ها هستند(در آینده سایر انواع کلکسیونهای قابل استفاده با for ؛ همچون کلکسیونهایی که به وسیله collection framework تعریف می شوند را بررسی می کنیم).

هر بار که حلقه تکرار می شود؛ عنصر بعدی در کلکسیون بازیابی و در itr-var ذخیره می شود. حلقه آنقدر تکرار می شود تا تمام عناصر در کلکسیون بازیابی می شود.چون متغیر تکرار؛ مقادیرش را از کلکسیون ها به دست می آورد؛type باید با نوع عناصر ذخیره شده در کلکسیون یکسان باشد(یا سازگار باشد). از این رو ؛type هنگام گردش در بین عناصر آرایه باید با نوع عناصر آنها سازگار باشد. برای درک انگیزه ابداع حلقه های سبک for-each ؛ نوع حلقه for ایی را در نظر بگیرید که این سبک جدید به عنوان جایگزین آن طراحی شده است.
اگرچه حلقه for-each آنقدر تکرار می شود تا تمام عناصر موجود در آرایه بررسی شوند؛اما این امکان وجود دارد که حلقه را با استفاده از عبارت break در همان مراحل اولیه قطع کرد.
نکته مهمی درباره حلقه سبکfor-each وجود دارد که باید به خوبی درک کنید. چون متغیر تکرار آن با آرایه مرتبط است؛ لازم است “فقط خواندنی” باشد. تخصیص مقدار به این متغیر؛ هیچ تاثیری بر آرایه ندارد. به عبارت دیگر؛ محتوای آرایه را نمی توانید از طریق تخصیص مقدار جدید به متغیر تکرار تغییر دهید. برنامه زیر را در نظر بگیرید:
01 //the for-each loop is essentially read-only.
02 Class NoChange{
03 Public static void main(string args[]) {
04 Int nums[ ] = {1,2,3,4,5,6,7,8,9,10};
05 For (int x:nums) {
06 System.out.print(x+” “);
07 X=x*10; //no effect on nums
08 }
09 System.out.println( );
10 For(int x : nums)
11 System.out.print(x+” “ );
12 System.out.println( );
13 }
14 }


نخستین حلقه for ؛ مقدار متغیر تکرار را به اندازه ۱۰۰ واحد افزایش می دهد. اما همانکونه که حلقه for نشان می دهد؛ این کار هیچ تاثیری بر آرایه nums ندارد. این نکته با خروجی زیر به اثبات رسیده است:

۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۱۰

۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۱۰

عبارات پرش

جاوا از سه عبارت پرشjump ، break,continue و return پشتیبانی می کند. این عبارات؛ کنترل را به بخش دیگری از برنامه تان انتقال می دهند.آنها را با هم بررسی می کنیم:

نکته: جاوا علاوه بر عبارت پرش مورد بررسی در اینunit؛ از روش دیگری برای تغییر جریان اجرای برنامه تان پشتیبانی می کند: از طریق مدیریت استثنا ها. مدیریت استثنا ها روش ساختار یافته ای در اختیارتان می گذارد که خطاهای زمان اجرا از طریق آن قابل به دام انداختن و مدیریت می شوند. این روش با کلمات کلیذی try,catch,throw,throws وfinally پشتیبانی می شود. در واقع مکانیزم مدیریت استثناها؛امکان پرش غیر محلیnonlocal را برای برنامه تان فراهم می سازد.از آنجایی که مدیریت استثنا ها؛ موضوع گسترده ای است؛ به طور جداگانه در unit های بعدی بررسی خواهند شد.

استفاده از break

عبارتbreak در جاوا سه کاربرد دارد. نخست اینکه؛ همان گونه که دیده اید؛ به اجرای متوالی عبارات در یکی از حالات عبارت switch پایان می بخشد. دوم اینکه از آن می توان برای خروج از حلقه استفاده نمود و سوم اینکه از آن می توان به صورت شکل متمدنی از goto استفاده نمود. دو کاربرد آخر را با هم بررسی می کنیم:

استفاده ازbreak برای خروج از حلقه ها

با استفاده ازbreak می توانید یک حلقه را فورا پایان ببخشید و از جمله شرطی و مابقی عبارت موجود در قسمتbody صرفنظر کنید.وقتی نوبت به اجرای عبارتbreak در یک حلقه می شود؛ اجرای حلقه به پایان رسیده و کنترل اجرای برنامه به نخستین عبارت پس از حلقه هدایت می شود:01 //using break to exit a loop.
02 Class BreakLoop{
03 Public static void main(string args[]) {
04 For (int i=0; i<100; i++){
05 If (i==10)break; //terminate loop if I is 10
06 System.out.println(“i:” +);
07 }
08 System.out.println(“Loop complete.”);
09 }
10 }


Out put:
I: 0
I: 1
I: 2
. . .
I: 9
Loop complete.

وقتی از عبارت break در مجموعه ای از حلقه های تو در تو استفاده شود؛ تنها اجرای داخلی ترین حلقه قطع می شود.

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

چنانچه عبارتbreak اجرای برنامهswitch را قطع کند؛ تاثیر آن تنها بر همان عبارت خواهد بود و نه حلقه در بر گیرنده آن.

نکته: break برای فراهم ساختن روش متعارف قطع اجرای حلقه ها طراحی نشده است. انجام این کار بر عهده جملات شرطی حلقه ها است. از عبارتbreak باید برای قطع اجرای حلقه ها تنها در صورت بروز شرایط ویژه استفاده نمود.

استفاده از break به عنوان نوعی goto

زبان جاوا فاقد عبارتgoto است چرا که عبارت مذبور ؛روشی برای انشعاب غیر شرطی فراهم نموده و موجب از بین رفتن ساختار یافتگی برنامه ها می شود.

انجام این کار معمولا سبس می شود تا درک و نگهداشت روتین هایgoto دار دشوار شود. این عبارت همچنین از برخی از بهینه سازیهای کامپایلر ها جلوگیری می کند. اما عبارت goto در برخی از موارد؛ساختاری ارزشمند و قانونی برای هدایت رو به جلو جریان برنامه هاست.

جاوا برای مدیریت اینگونه شرایط؛از شکل گسترده ای از عبارتbreak پشتیبانی می کند. با استفاده از این فرم از عبارتbreak می توانید ازاجرای یک یا چند بلوک صرفنظر کنید.لزومی ندارد که این گونه بلوک ها؛ در یک حلقه یا عبارتswitch باشند. این کار برای هر بلوکی میسر است. به علاوه می توانید دقیقا مشخص کنید که اجرای برنامه ها از کجا ادامه یابد؛ چرا که این فرم از عبارتbreak همراه با برچسبهاlabel به کار برده می شود.1 Break label;


Label نام برچسبی است که نشان دهنده بلوک مورد نظر است.
استفاده از continue

گاهی اوقات لازم است که اجرای حلقه پیش از رسیدن به انتها تکرار شود. این کار با عبارتcontinue انجام می شود. این عبارت در حلقه های while و do-while سبس انتقال مستقیم کنترل به جمله شرطی کنترل کننده حلقه می شود. در حلقه for کنترل نخست به قسمت interation و سپس به جمله شرطی عبارتfor هدایت می شود. در هر سه حلقه جاوا؛ عبارات پس از continue (تا انتهای حلقه)نادیده انگاشته می شوند.01 //demonstrate continue
02 Class Continue{
03 Public static void main(string args[]){
04 For (int i=0 ; i<10 ; i++) {
05 System.out.print( I + “ “ ) ;
06 If (i% 2 == 0) continue;
07 System.out.println ( “ “ );
08 }
09 }
10 }


با استفاده از عملگر% بررسی می شود که مقدارi زوج است یا خیر. اگر چنین باشد ؛حلقه بون چاپ کاراکتر”سطر جدید” ادامه می یابد.

Return

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

با استفاده از عبارتreturn در متدها می توان کنترل اجرا را در هر لحظه به روتین فراخوان متد بازگرداند. از این رو اجرای متدی که در آن اجرا می شود را فورا به پایان می رساند. این نکته را در یک مثال نشان می دهیم:1 //demonstrate return.
2 Class Return{
3 Public static void main(string args[]) {
4 Boolean t= true ;
5 System.out.println(“Before the return.”) ;
6 If (t) return ; //return to caller
7 System.out.println(“this wont execute.”);
8 }
9 }


آخرین نکته : در برنامه بالا if(t) ضروری است. کامپایلر جاوا در صورت عدم وجود آن؛ پیام خطای”unreachable code” را نمایش می دهد.چرا که برای کامپایلر مشخص می شود که آخرین عبارتprintln هیچگاه اجرا نمی شود. برای پیشگیری از این خطا از عبارتif برای گول زدن کامپایلر جهت نشان دادن نکته مورد نظر استفاده شده است.
Mino آنلاین نیست.   پاسخ با نقل قول
قدیمی 04-18-2012   #15
Mino
عضو تالار
 

تاریخ عضویت: Feb 2012
محل سکونت: خوزستان، اهواز،
نوشته ها: 802
تشکرهای ایشان: 22,059
33,363بار در12,628پست از ایشان تشكر شده است

صندوق مدال ها

پیش فرض

درس 9
کلاس ها در هسته مرکزی جاوا جا دارند. کلاس ها؛ساختار منطقی هستند که کل زبان جاوا بر روی آن ساخته شده است زیرا شکل و ماهیت شی ء ها را تعریف می کنند. بدین ترتیب کلاس ها پایه و اساس برنامه سازی شی ء گرا را در جاوا تشکیل می دهند . هر موضوعی که بخواهید در برنامه های جاوا پیاده سازی کنید؛می بایست در یک کلاس نهان encapsulated شود.
اصول کلاس ها :
شاید مهمترین نکته ای که باید در مورد کلاس ها یاد بگیریم آن است که نوع جدیدی از داده ها را تعریف می کند. داده های نوع جدید را پس از تعریف شدن می توان برای ایجاد شی ء های نوع مورد نظر به کار برد. از این رو هر کلاس؛ الگویی template برای یک شیء است و هر شیء هم نمونه ای instance از یک کلاس به شمار می آید. چون هر شی ء نمونه ای از یک کلاس است تغلب می بینیم که دو واژه شیء و نمونه به جای یکدیگر به کار برده می شوند.
شکل عمومی کلاس ها :
وقتی کلاسی را تعریف می کنید؛ ماهیت و فرم دقیق آن معرفی می شود. این کار با مشخص کردن داده های درون آن و روتین هایی که بر روی آن داده ها عمل می کنند؛انجام می گردد.روتین های هر کلاس؛ رابز منتهی به داده های آن را تعریف می کنند.
هر کلاس با استفاده از کلمه کلیدی class تعریف می شود. شکل عمومی تعریف هر کلاس در ذیل نشان داده شده است:
01 Class classname{
02 Type instance-variable1;
03 Type instance-variable2;
04 //…
05 Type instance-variable N;
06
07 Type methodname1(parameter-list){
08 //body of method
09 }
10 Type methodname2(parameter-list){
11 //body of method
12 //…
13 Type methodnameN(parameter-list){
14 //body of method
15 }


داده ها یا متغیر هایی که در هر کلاس تعریف می شوند؛ نمونه متغیر instance variable نامیده می شوند. روتین ها نیز در متد ها جای میگیرند. به طور کلی؛ به متد ها و متغیر هایی که در هر کلاس تعریف می شوند؛اعضای member کلاس گفته می شود. در بیشتر کلاس ها؛ متد های تعریف شده برای هر کلاس هستند که بر روی نمونه متغیر ها کار می کنند و به آنها دستیابی دارند. از این رو؛ این متد ها هستند که چگونگی استفاده از داده های هر کلاس را تعیین می کنند.
دلیل اینکه متغیرهای هر کلاس ، نمونه متغیر خوانده می شوند ، آن است که هر نمونه از یک کلاس (یعنی ، هر شی از یک کلاس) ، کپی خاص خود را از متغیرها دارد . از این رو ، داده های هر شیء ،جداگانه و خاص خود آن بوده و با داده های یک شیء دیگر یکسان نیستند . به زودی به بررسی این نکته خواهیم پردداخت ، اما این نکته مفهوم مهمی است که باید پیشاپیش فرابگیرید.
تمام متدها همان شکل عمومی main() را دارند که تا به حال به کاربرده ایم . اما ، بیشتر متدها به عنوان یک متد ایستا یا عمومی مشخص نمی شوند . توجه داشته باشید که در شکل عمومی کلاس ها ، متدی به نام main() مشخص نمی شود . کلاس های جاوا نیاز به متد main() ندارند . تنها زمانی چنین متدی مشخص می شود که کلاس مورد نظر ، نقطه آغازین برنامه تان باشد . به علاوه ، اپلت ها اصلا نیاز به متدی به نام main() ندارند .
توجه : برنامه سازان C++ توجه داشته باشند که معرفی کلاس و پیاده سازی متدها در یکچا ذخیره می شوند و به طور جداگانه تعریف نمی شوند . این امر گاهی اوقات سبب ایجاد فایل های java . بسیار بزرگ می شود ، چه آنکه هر کلاس باید کلا در یک فایل واحد تعریف شود . دلیل گنجاندن این ویژگی در طراحی جاوا آن است که احساس می شد که در دراز مدت ، داشتن

یک کلاس ساده
مطالعه کلاس ها را با یک مثال ساده آغاز می کنیم . برای این کار کلاسی به نام BOX تعریف می کنیم که دارای سه نمونه متغیر به نام Width , height , depth است . در حال حاضر ، BOX فاقد هر گونه متد است .1 Class box {
2 Double width ;
3 Double height ;
4 Double depth ;
5 }


همان گونه که گفته شد ، هر کلاس ، نوع جدیدی از داده ها را تعریف می کند . در این مثال خاص ، نوع جدیدی که ایجاد می شود ، BOX نامیده شده است . از این نام برای تعریف شیء های نوع BOX استفاده خواهد شد . مهم است به خاطر بسپارید که تعریف هر کلاس جدید تنها سبب اینجاد یک الگو می شود ؛ یک شیء واقعی ایجاد نمی شود . از این رو ، تعریف کلاس BOX در بالا سبب ایجاد هیچ شیئی از نوع BOX نمی شود .
برای آنکه یک شیء BOX ایجاد شود ، می بایست از عباراتی همچون سطر زیر استفاده کنید .1 BOX mybox = new box () ;
2 // creat a box object called mybox


پس از آنکه عبارت بالا اجرا شد ، mybox به عنوان نمونه ای از BOX ایجاد خواهد شد . از این رو ، یک واقعیت «فیزیکی» از کلاس BOX ایجاد خواهد شد . فعلا ، نگران جزئیات این عبارت نباشید .
باز هم لازم به ذکر است که هر گاه نمونه ای از یک کلاس را ایجاد می کنید ، شیئی ایجاد می شود که نسخه خاص خودش را از هر یک از نمونه متغیرهای تعریف شده در آن کلاس خواهد داشت . از این رو ، هر شی BOX ، نسخه های خاص خودش را از نمونه متغیرهای Width , height , depth خواهد داشت . برای دستیابی به این متغیرها باید از عملگر نقطه (.) استفاده کنید . این عملگر ، نام شیء را با نام «نمونه متغیر» مرتبط می کند . به عنوان مثال ، برای آنکه مقدار ۱۰۰ را به متغیر Width از mybox تخصیص دهید ، از عبارت زیر استفاده کنید :1 Mybox . width = 100


عبارت بالا برای کامپایلر مشخص می کند که مقدار ۱۰۰ را به نسخه ای از width که در شی mybox است تخصیص دهد . به طور کلی ، از عملگر نقطه (.) برای دستیابی به نمونه متغیرها و متدهای موجود در یک شیء استفاده می شود . در برنامه زیر از کلاس BOX استفاده شده است :
01 /* A program that uses the BOX class.
02 Call this file BOXDemo.java
03 */
04 Class BOX {
05 Double width ;
06 Double height ;
07 Double depth ;
08 }
09
10 //this class declares an object of type BOX .
11 Class boxvemo {
12 Public static void main (string args[]) {
13 Box mybox = new box ();
14 Double vol ;
15 // assign values to mybox’s instance variables
16 Mybox.width = 10;
17 Mybox.height = 20;
18 Mybox.depth = 15;
19 // compute volume of box
20 Vol = mybox.width*mybox .height *mybox.depth;
21 System.out.println(“volume is ”+vol) ;
22 }
23 }


می بایست فایل حاوی این برنامه را Boxdemo.java بنامید ، چرا که متد main() در کلاسی است که Boxdemo نام دارد ، و نه BOX . کامپیوتر جاوا هر کلاس را به طور خودکار در فایل .class ایجاد خواهد شد ؛ یکی برای Box و یکی هم برای Boxdemo . کامپیوتر جاوا هر کلاس را به طور خودکار در فایل .class خاص خودش قرار می دهد . لزومی ندارد که هر دو کلاس BOX و Boxdemo دریک فایل دخیره شوند. هر یک از کلاس ها را می توانید در فایل های خاص خودشان قرار دهید : box.java و boxdemo.java .
برای آنکه این برنامه را اجرا کنید ، باید boxdemo.class را اجرا کنید. وقتی این کار را انجام می دهید ، خروجی زیر را خواهید دید :

Volume is 3000.0

همان گونه که پیش از این گفته شد ، هر شیء نسخه های خاص خودش را از نمونه متغیرها خواهد داشت. این بدین معناست که اگر دو شی نوع BOX داشته باشید ، هر یک از آنها ، نسخه های خاص خودشان را از width.depth و height خواهند داشت . مهم است بدانید که تغییراتی که در نمونه متغیرهای یک شی ایجاد می شوند، هیچ تاثیری بر نمونهه متغیرهای شیء دیگر نخواهند داشت. به عنوان مثال ، در برنامه زیر دو شیء BOX تعریف شده است :
01 // this program declares two box objects .
02 Class Box {
03 Double width ;
04 Double height ;
05 Double depth ;
06 }
07 Class boxDemo2 {
08 Public static void main (string args[]) {
09 Box mybox1 = new box ();
10 Box mybox2 = new box ();
11 Double vol ;
12
13 // assign values to mybox’s instance variables
14 Mybox1.width = 10;
15 Mybox1.height = 20;
16 Mybox1.depth = 15;
17 /* assign different values to mybox’s instance variables*/
18 Mybox2.width = 3;
19 Mybox2.height = 6;
20 Mybox2.depth = 9;
21
22 // compute volume of first box
23 Vol = mybox1.width*mybox1 .height *mybox1.depth;
24 System.out.println(“volume is ”+vol) ;
25
26 // compute volume of second box
27 Vol = mybox2.width*mybox2 .height *mybox2.depth;
28 System.out.println(“volume is ”+vol) ;
29 }
30 }


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

Volume is 3000.0
Volume is 162.0

همانگونه که می بینید ، داده های mybox1 ، کاملا جدای از داده های موجود در mybox2 هستند .

Mino آنلاین نیست.   پاسخ با نقل قول
قدیمی 04-18-2012   #16
Mino
عضو تالار
 

تاریخ عضویت: Feb 2012
محل سکونت: خوزستان، اهواز،
نوشته ها: 802
تشکرهای ایشان: 22,059
33,363بار در12,628پست از ایشان تشكر شده است

صندوق مدال ها

پیش فرض

بقیه درس 9
شیوه تعریف کردن شیءها
همان گونه که در بالا شرح داده شد ، وقتی کلاسی را ایجاد می کنید ، در واقع یک نوع جدید برای داده ها ایجاد می شود . از این نوع جدید می توانید برای تعریف کردن شیئ هایی از آن نوع استفاده کنید . اما رسیدن به شئ های یک کلاس ، نوعی فرآیند دو مرحله ای است . نخست اینکه ، باید متغیری است که می تواند به یک شئ ارجاع داشته باشد. دوم اینکه ، می بایست یک نسخه فیزیکی واقعی از شئ به دست آورید و آن را به آن متغیر تخصیص دهید. این کار را می توانید با استفاده از عملگر new انجام دهید. عملگر new ، حافظه ای را به طور پویا (یعنی در زمان اجرا) به شئ تخصیص می دهد و نشانی آن را بر می گرداند. این نشانی سپس در متغیر ذخیره می شود . از این رو ، تمام شئ های نوع کلاس در جاوا باید به طور پویا تخصیص یابند . اینک به جزئیات این رویه می پردازیم .
درنمونه برنامه های زیر از سطری مشابه عبارت زیر برای تعریف شیئی از نوع BOX استفاده خواهد شد:1 Box mybox = new box();


دو مرحله پیش گفته در عبارت بالا ترکیب شده اند . عبارت بالا را می توان برای نشان دادن هر یک از مراحل به صورت زیر بازنویسی کرد :1 Box mybox ; // declare refrence to object
2 Mybox = new box (); // allocate a box object


درسطر نخست ، mybox به عنوان نشانی شیئی از نوع box تعریف می شود . پس از اجرای این خط ، مقدار null در mybox ذخیره خواهد شد که نشانگر آن است که متغیر هنوز به هیچ شیء واقعی ارجاع ندارد . هر گونه اقدام برای استفاده از mybox در این مرحله منجر به بروز خطای زمان کامپایل خواهد شد . سطر دوم هم موجب تخصیص شیء واقعی و تخصیص نشانی آن به mybox می شود . پس از اجرای سطر دوم ، می توانید از mybox می شود . پس از اجرای سطر دوم ، می توانید از mybox به گونه ای استفاده کنید که گویی یک شیء Box است. اما mybox صرفا نشانی حافظه شیء BOX واقعی را نگهداری می کند . تاثیر این دو سطر در شکل ۱-۶ به تصویر کشیده شده است .
توجه : خوانندگانی که با C/C++ آشنایی دارند ، احتمالا متوجه شده اند که به نظر می رسد که نشانی شیء ها مشابه نشانه روها باشد . این گمان و تصور واقعا درست است . نشانی هر شیء ف مشابه نشانه رو نقطه ای از حافظه است . تفاوت اصلی – و کلید امنیت جاوا – آن است که نشانی همچون نشانه رو ها قابل پردازش و مدیریت نیست . از این رو ، ارجاع آنها را نمی توان به نقطه دلخواهی از حافظه تغییر داد و یا همچون یک صیحیح با آنها کار کرد .


نگاهی دقیقتر به new

همانگونه که در قسمت پیش شرح داده شد ، عملگر new ، حافظه هر شیء را به طور پویا تخصیص می دهد .شکل کلی آن در ذیل نشان داده شده است :

Class-var = new classname();

Class-var ، متغیری از نوع کلاسی است که ایجادمی شود ، classname نام کلاسی است که نمونه ای از آن ایجاد می شود . constructor کلاس با نام کلاس و دو پرانتزی که پس از آن قرار گرفته اند ، مشخص می شود . constructor مشخص می کند که هنگام ایجاد شیئی از نوع کلاس ، چه اتفاقی رخ می دهد . constructor های خاص خودشان را در تعریف کلاس مشخص می کنند . اما ، اگر constructor به طور صریح مشخص نشود ، در آن صورت جاوا آن را به طور خودکار تامین می کند . در خصوص کلاس box همین طور است . فعلا از constructor پیش فرض استفاده می کنیم . به زودی خواهید دید که چگونه می توانید constructor های خاص خود را تعریف کنید .
در این مقطع ممکن است از خود بپرسید که چرا نیازی به استفاده از new برای مواردی چون اعداد صحیح یا کارکترها نیست . پاسخ این پرسش آن است که انواع داده های پایه جاوا به صورت شیء پیاده سازی نمی شوند. بلکه ، به صورت متغیرهای «معمولی» پیاده سازی می شوند . این کار به خاطر بازدهی بیشتر انجام می گیرد . همان گونه که خواهید دید ، شیء ها ،ویژگیها و خصوصیات زیادی دارند که لازم است طرز برخورد با آنها نسبت به انواع داده های پایه متفاوت باشد . با عدم تحمیل سرباز خاص شیء ها به انواع داده های پایه ، جاوا قادر به پیاده سازی کارآمدتر انواع داده های پایه می شود . در آینده ، با آن دسته از نگارشهای «شیئی» انواع داده های پایه آشنا خواهید شد که برای استفاده در شرایطی مهیا شده اند که همان نوع شیء ها مورد نیاز می باشند .
مهم است به خاطر داشته باشید که new حافظه شیء ها را در طی اجرا ایجاد کنند . اما ، از آنجایی که حافظه محدوداست ، این احتمال وجود دارد که new به دلیل عدم وجود حافظه کافی نتواند حافظه لازم برای یک شیء را تخصیص دهد . اگر چنین اتفاقی رخ دهد . استثنا زمان اجرا پیش خواهد آمد (چگونگی مدیریت این استثنا ها را د آینده بررسی خواهیم کرد)..
تمایز بین کلاس ها و شیء ها را یک مرتبه دیگر مرور می کنیم . هر کلاس، نوع جدیدی از داده ها را ایجاد می کند که می توان برای ایجاد شیء ها به کار برد . یعنی ، هر کلاس نوعی چارچوب منطقی ایجاد می کند که رابطه بین اعضایش را تعریف می کند . وقتی شیئی از یک کلاس معین را تعریف می کنید ، در واقع نمونه ای از آن کلاس ایجاد می کنید . از این رو ، هر کلاس ، نوعی ساختار منطقی است . هر شیء نیز نوعی واقعیت فیزیکی است (یعنی هر شیء فضایی را در حافظه اشغال می کند) . مهم است که این تمایز را به ذهن خود بسپارید .
تخصیص متغیرهای ارجاع به شیء
وقتی عمل تخصیص انجام می گیرد، عملکرد متغیرهای ارجاع به شیء با آنچه انتظار دارید تفاوت دارد . به عنوان مثال ، فکر می کنید دو عبارت زیر چه عملی انجام می دهند؟1 Box b1 = new Box () ;
2 Box b2 = b1;


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


اگر چه b1 و b2 هر دو به یک شیء ارجاع دارند ، اما به هیچ شکل دیگر مرتبط نیستند . به عنوان مثال ، تخصیص مقداری دیگر به b1 صرفا سبب قطع ارتباط آن با شیء اولیه می شود که البته ، هیچ تاثیری بر b2 نخواهد داشت . به عنوان مثال :1 Box b1 = new Box();
2 Box b2 = b1 ;
3 // …
4 B1= null ;


B1 در اینجا با null مقدار دهی شده ، اما b2 هنوز به همان شیء اولیه ارجاع دارد .
نکته : وقتی مقدار متغیر ارجاع به شیء را به متغیر دیگری از همان نوع تخصیص می دهید ، هیچ نسخه ای شیء ایجاد نمی شود ، بلکه تنها نسخه ای از همان نشانی (ارجاع) ایجاد می شود..
Mino آنلاین نیست.   پاسخ با نقل قول
قدیمی 04-18-2012   #17
Mino
عضو تالار
 

تاریخ عضویت: Feb 2012
محل سکونت: خوزستان، اهواز،
نوشته ها: 802
تشکرهای ایشان: 22,059
33,363بار در12,628پست از ایشان تشكر شده است

صندوق مدال ها

پیش فرض

<b>درس 10
کلاس ها معمولا از دو چیز تشکیل می شوند : نمونه متغیرها و متدها . موضوع متدها بسیار گسترده است . چرا که جاوا قدرت و انعطاف پذیری زیادی را در آنجا جای داده است . در حقیقت ، بیشتر فصل آتی به متدها اختصاص یافته است. اما اصولی وجود دارند که می بایست هم اینک فرا بگیرند تابتوانید روند افزودن متدها به کلاس های خود را آغاز نمایید .
شکل کلی هر متد به صورت زیر است :
1 Type name (Parameter-list) {
2 // body of method
3 }


.type نوع داده هایی را مشخص می کند که متد باز می گرداند . type می تواند هر یک انواع مورد بررسی قبلی باشد ، از جمله انواع کلاس هایی که خودتان ایجاد می کنید. چنانچه متد چیزی را برنگرداند، type باید void باشد . نام متد نیز به وسیله name مشخص می شود. از هر شناسه معتبری می توانید به عنوان نام استفاده کنید ؛ البته به غیر از مواردی که برای اقلام موجود در همان محدوده جاری استفاده شده اند . parameter-list ، فهرست زوجهایی (نوع و شناسه) اشت کهبا کاما از یکدیگر جدا می شوند . پارامترها اساسا متغیرهایی هستند که مقدار آرگومان های ارسالی به متد را هنگام فراخوانی آن دریافت می کنند . چنانچه متد پارامتری نداشته باشد ، این فهرست خالی خواهد بود .
متدهایی که نوع مقدار حاصل از فراخوانی آنها چیزی به غیر از void باشد، مقداری را با استفاده از عبارت return به روتین فراخوان بازمی گردانند1 return value;


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

افزودن متد به کلاس Box

اگر چه ایجاد کلاس هایی که تنها حاوی داده باشند کاملا درست است ، اما این امر به ندرت رخ می دهد. در بیشتر مواقع از متدها برای دستیابی به نمونه متغیرهای تعریف شده در کلاس ها استفاده خواهدشد . در حقیقت ، متدها ، رابط دستیابی به بیشتر کلاس ها را تعریف می کنند . این امر به ایجاد کننده کلاس ها امکان می دهد تا شمای ساختارهای داده ای مرتبط با کلاس را پشت سر متدهای شفاف تر پنهان نماید . علاوه بر تعریف متدهایی که دستیابی به داده ها را فراهم می سازند ، امکان تعریف متدهایی که توسط خود کلاس ها و به طور داخلی مورد استفاده قرار می گیرند نیز فراهم شده است .
اینک کار خود کلاس ها و به طور داخلی مورد استفاده قرار می گیرند نیز فراهم شده است .
اینک کار خود را با افزودن متدی به کلاس Box آغاز می کنیم . ممکن است در حین بررسی برنامه های پیشین این فکر به ذهنتان خطور کرده باشد که محاسبه حجم مکعب بهتر است توسط خودکلاس Box انجام شود ، و نه کلاس BoxDemo ، به ذهنتان خطور کرده باشد که محاسبه حجم مکعب بهتر است توسط خود کلاس Box بیفزایید .
01 // This program includes a method inside the box class .
02 Class Box {
03 Double width;
04 Double height;
05 Double depth;
06
07 // display volume of a box
08 Void volume () {
09 System.out.print(“volume is “);
10 System.out.println(width * height * depth);
11 }
12 }
13 Class BoxDemo3 {
14 Public static void main (string args []) {
15 Box mybox1 = new Box ();
16 Box mybox2 = new Box();
17
18 // assign values to mybox1’s instance variables
19 Mybox1 . width = 10 ;
20 Mybox1.height = 20 ;
21 Mybox1 . depth = 15 ;
22 /* assign different values to mybox2’s
23 Instance variables */
24 Mybox2 . width = 3 ;
25 Mybox2.height = 6;
26 Mybox2.depth = 9;
27
28 // display volume of first box
29 Mybox1.volume () ;
30 //display volume of second box
31 Mybox2.volume();
32 }
33 }


خروجی برنامه در ذیل آورده شده است که البته با خروجی مثال پیش یکسان است .

Volume is 3000.0
Volume is 162.0

به دو سطر زیر توجه کنید :
1 Mybox1 .volume() ;
2 Mybox2.volume();


سطر نخست سبب فعال شدن متد volume() برای mybox1 می شود . یعنی ، با استفاده از نام شیء و سپس عملگر نقطه (.) ، volume () برای کار بر روی داده های mybox1 فراخونده می شود. از این رو ، mybox1.volume() موجب می شود که توسط mybox2 تعریف شده است . هر بار که volume() فعال می شود، حجم مکعب مربوط نمایش داده می شود.
اگر با مفهوم فراخوانی متدها آشنا نباشید ، بحث زیر به شفافیت موضوع کمک خواهد کرد . وقتی mybox1.volume() اجرا می شود ، سیستم «زمان – اجرای» جاوا ، کنترل را به روتین volume() انتقال می دهد . پس از اجرای عبارات موجود در volume () ، کنترل به روتین فراخوان بازگردانده می شود ، و سطر بعدی آن اجرا می شود . به طور کلی تر ، هر متد در جاوا ، روشی برای پیاده سازی سابر روتین هاست .
نکته بسیار مهمی درباره محتوای متد volume () وجود دارد کهباید به آن توجه کنید : ارجاع به نمونه متغیرهای depth , height , width به صورت مستقیم و بدون قرار گرفتن نام شیء و عملگر نقطه (.) پیش از آنها ، صورت می گیرد . وقتی متدی از نمونه متغیری استفاده می کند که توسط کلاس خودش تعریف شده است ، این کار به طور مستقیم و بدون ارجاع به شیء و بدون استفاده از عملگر نقطه (.) انجام می شود . اگر کمی در این باره فکر کنید ، درک آن آسان است . هر متد همیشه نسبت به شیئی از کلاس خودش فعال می شود . از این رو ف نیازی به مشخص کردن مجدد شیء در متد نیست . این بدین معناست که depth, height , width در متد volume () ، به طور ضمنی به نسخه هایی از این متغیرها ارجاع دارند که در همان شیئی قرار دارند که volume () را فعال می کند .
این موضوع را سریعا مرور می کنیم . وقتی دستیابی به نمونه متغیرها به وسیله روتینی انجام می گیرد که در همان کلاس تعریف متغیرها تعریف نشده است ، در آن صورت باید این کار از طریق نام شیء و عملگر نقطه (.) انجام شود اما ، وقتی این کار به وسیله روتینی انجام می شود که بخشی از همان کلاس مربوط به متغیرهاست، در آن صورت متغیرها به طور مستقیم قابل ارجاع می باشند . این مطلب درباره متدها نیز صادق است .




</b>
Mino آنلاین نیست.   پاسخ با نقل قول
قدیمی 04-18-2012   #18
Mino
عضو تالار
 

تاریخ عضویت: Feb 2012
محل سکونت: خوزستان، اهواز،
نوشته ها: 802
تشکرهای ایشان: 22,059
33,363بار در12,628پست از ایشان تشكر شده است

صندوق مدال ها

پیش فرض

بقیه درس 10

بازگرداندن مقادیر

اگر چه پیاده سازی volume () سبب انجام محاسبه حجم مکعب در همان کلاس box می شود ، اما بهترین روش برای انجام این کار به شمار نمی آید . به عنوان مثال ، اگر بخش دیگری از برنامه تان نیاز به داشتن حجم مکعب توسط volume () محاسبه و مقدارش به روتین فراخوان ، بازگردانده شود .مثال زیر ، نگارش بهبود یافته ای از برنامه پیشین است که همین کار را انجام می دهد :
01 // Now , volume () returns the volume of a box .
02
03 Class box {
04 Double width;
05 Double height;
06 Double depth;
07
08 // compute and return volume
09 Double volume () {
10 Return width * height * depth;
11 }
12 }
13 Class boxdemo4 {
14 Public static void main (string args[]) {
15 Box mybox1 = new box() ;
16 Box mybox2 = new box ();
17 Double vol ;
18
19 // assign values to mybox1’s instance variables
20 Mybox1.width=10;
21 Mybox1.height=20;
22 Mybox1.depth = 15 ;
23 /* assign different values to mybox2’s
24 Instance variables */
25 Mybox2.width=3;
26 Mybox2.height=6;
27 Mybox2.depth = 9 ;
28 // get volume of first box
29 Vol = mybox1.volume();
30 System.out.println(“volume is” + vol) ;
31
32 // get volume of decond box
33 Vol = mybox2.volume() ;
34 System .out.println(“volume is” + vol);
35 }
36 }


همانگونه که ملاحظه می کنید ، وقتی volume() فرا خوانده می شود ، در سمت راست عبارت تخصیص مورد نظر قرار داده می شود. متغیر سمت چپ عبارت تخصیص (vol در این مثال)، مقدار حاصل از فراخوانی volume() را دریافت خواهد کرد . از این رو ، پس از اجرای1 Vol = mybox1.volume();


مقدار mybox1.volume() عدد ۳۰۰۰ خواهد بود که در vol ذخیره می شود .
دو نکته مهم درباره مقدادیر حاصل از فراخوانی متدها وجود دارد که باید به خوبی با آنها آشنا باشید :
• نوع داده های حاصل از فراخوانی متد باید با نوعی که در تعریف متد مشخص شده است ، سازگار باشد . به عنوان مثال ، اگر نوع مقداری که یک متد باز می گرداند ، Boolean باشد ، نمی توانید مقدار صحیحی را بازگردانید .
• متغیر دریافت کننده مقدار حاصل از فراخوانی متد (مثلا vol دراین مثال )، باید با نوعی که در تعریف متد مشخص شده است ، سازگار باشد .
یک نکته دیگر : برنامه بالا را می توان به صورت کاآمدتری بازنویسی کرد ، چرا که نیازی به متغیر vol نیست . فراخوانی volume () رامی توان مستقیما درعبارت println انجام داد .1 System.out.println(“volume is” + mybox1.volume());


در این حالت ، وقتی println اجرا می شود ، mybox1.volume() به طور خودکار فراخوانده می شود و مقدار حاصل از آن به println() ارسال خواهد شد .
افزودن متدهای پارامتریک
اگر چه برخی از متدها نیاز به پارامتر ندارند ، اما بیشتر متدها این گونه نیستند . پارامترها امکان عمومیت بخشیدن به متدها را فراهم می سازند . یعنی متدهای پارامتریک می توانند بر روی انواع داده ها عمل کنند ، و یا در شرایط نسبتا مختلف مورد استفاده قرار گیرند .برای درک این نکته به مثال بسیار ساده زیر توجه کنید . متد زیر ، مجذور عدد ۱۰ را باز می گرداند :
1 Int square()
2 {
3 Return 10 * 10;
4 }


اگر چه این متد واقعا واقعا مجذور عدد ۱۰ را باز می گرداند ، اما کاربرد آن بسیار محدود است . اما اگر متد رابه گونه ای تغییر دهیم تا پارامتری را همچون مثال زیر دریافت کند ، در آن صورت square() بسیار مفید تر می شود .
1 Int square(int i)
2 {
3 Return i+1*I;
4 }


بدین ترتیب square() اینک مجذور هر مقداری که با آن فراخوانده می شود را باز می گرداند . یعنی ، square() به متد همه منظوره ای مبدل شده است که به جای عدد ۱۰ ، مجذور هر عدد صحیح را محاسبه می کند .
به مثال زیر توجه کنید :1 Int x,y;
2 X = square(5) ,
3 // x equals 25
4 X = square(9) ,
5 // z equals 81
6 Y=2;
7 X = square (y) ,
8 // x equal 4


در نخستین عبارت فراخوانی square() ، عدد ۵ به پارامتر i ارسال خواهد شد . در عبارت دوم ، i مقدار ۹ را دریافت خواهد کرد . در سومین عبارت فراخوانی ، مقدار y ، که در این مثال ۲ می باشد ، ارسال خواهد شد .
حفظ تمایز بین دو واژه پارامتر و آرگومان از اهمیت خاصی برخوردار است . منظور از پارامتر ، متغیری است که توسط متد تعریف می شود و وقتی متد فراخوانده می شود ، مقداری را دریافت می کند . به عنوان مثال ، در متد بالا ، i پارامتر به شمار می آید . منظور از آرگومان ، مقداری است که هنگام فعال سازی متد به آن ارسال می شود . به عنوان مثال ، در square(100)، عدد ۱۰۰ به عنوان آرگومان ارسال می شود . در متد square() پارامتر i، آن مقدار را دریافت می کند .
با استفاده از یک متد پارامتری می توانید کلاس box رابهبود بخشید . در مثالهای پیش ، ابعاد هر مکعب می بایست به طور جداگانه و با استفاده از چند عبارت به صورت زیر مشخص می شدند :
1 Mybox1.width=10;
2 Mybox1.height=20;
3 Mybox1.depth = 15 ;


اگر چه عبارات بالا به درستی کار می کنند ، اما به دو دلیل دردسرساز هستند.نخست اینکه ، مقداردهی جداگانه متغیرها مشکل و مستعد خطاست . به عنوان مثال ، فراموش کردن مقدار دهی هر یک از ابعاد بسیار آسان است . دوم اینکه ، در برنامه هایی که به خوبی طراحی شده باشند ، دستیابی به نمونه متغیرها باید تنها از طریق متدهای تعریف شده در کلاس خودشان صورت پذیرد . در آینده ، به راحتی می توانید رفتار هر متدی را تغییر دهید : اما نمی توانید رفتار نمونه متغیرهای قابل دسترسی را تغییر دهید .
از این رو ، رویه بهتر برای تعیین ابعاد مکعب ، ایجاد متدی است که ابعاد مکعب را در پارامترهایش دریافت و هر یک از نمونه متغیرها را مقدار دهی کند . این مفهوم به وسیله برنامه زیر پیاده سازی است :01
//this program uses a parameterized method.
02 Class box {
03 Double width;
04 Double height;
05 Double depth;
06 //compute and return volume
07 Double volume() {
08 Returne width *height*depth;
09 }
10 // sets dimensions of box
11 Void setdim(double w,double h, double d) {
12 Width = w;
13 Height = h;
14 Depth = d;
15 }
16 }
17 Class boxdemo5 {
18 Public static void main (string arg[]) {
19 Box mybox1 = new box();
20 Box mybox2 =newbox();
21 Double vol;
22 // initialize each box
23 Mybox1.setdim(10,20,15);
24 Mybox2.setdim(3,6,9);
25 //get volume of first box
26 Vol = mybox1.volume();
27 System.out.println(“volume is”+vol);
28 //get volume of second box
29 Vol=mybox2.volume();
30 System.out.println(“volume is”+ vol);
31 }
32 }


همانگونه که ملاحظه می کنید ، متد setdim() برای تعیین ابعاد هر مکعب به کار برده می شود . به عنوان مثال ، وقتی عبارت زیر اجرا می شود،
1 Mybox1.setdim(10,20,15);


10 به پارامتر w، ۲۰ به پارامتر h و ۱۵ به پارامتر d کپی می شود . مقادیر w,h,d سپس در setdim() به ترتیب به width,height, depth کپی می شوند .
مفاهیم مطروحه در قسمتهای پیش برای بسیاری از خوانندگان آشنا خواهند بود . اما ، اگر مواردی چون فراخوانی متدها ، آرگومان ها و پارامترها برایتان تازگی دارند ، بهتر است پیش از ادامه ، زمانی را صرف آزمایش آنها نمایید فعال سازی متدها ، پارامترها و مقادیر حاصل از فراخوانی متدها ، از مفاهیم اساسی و پایه برنامه سازی در جاوا به شمار می آیند .

Constructorها
مقدار دهی اولیه تمام متغیرهای یک کلاس هر بار به هنگام ایجاد نمونه ای از آن، کسل کننده خواهد بود . حتی با وجود افزودن توابع مناسبی چون setdim()، ساده تر و دقیقتر است که تمام کارهای مقدار دهی اولیه را در همان لحظه ایجاد شیء انجام دهید . چون این نیاز بسیار متداول است ، جاوا این امکان را فراهم ساخته تا شیء ها خودشان رابه هنگام ایجاد ، مقدار دهی کنند . این مقدار دهی خودکار ، از طریق استفاده از یک Constructor انجام می شود .
Constructor ، یک شیء را به محض ایجاد مقدار دهی می کند . نام آن با نام کلاسی که در آن قرار دارد یکسان بوده و از نظر ساختار گرامری نیز مشابه متدهاست . هر Constructor پس از تعریف ، به طور خودکار به محض ایجاد شیء فراخوانده می شود ؛ پیش از تکمیل کار عملگر Constructor.new ها قدری عجیب به نظر می آیند ، چرا که هیچ مقداری را باز نمی گردانند ، حتی void . دلیل این امر آن است که نوع ضمنی مقدارشان ف همان نوع کلاس است . این وظیفه Constructor هاست که وضعیت داخلی یک شیء را در همان ابتدای کار تعیین کنند (مقدار دهی اولیه)، تا روتینی که نمونه ای از کلاس را ایجاد می کند ،فورا شیء قابل استفاده و مقدار دهی شده ای داشته باشد .
مثال box را می توانید به گونه ای بازنویسی کنید تا ابعاد مکعب به طور خودکار هنگام ایجاد شیء مقدار دهی شوند . برای انجام این کار ، setdim() را با یک Constructor جایگزین کنید . این کار را با تعریف Constructor ساده ای که ابعاد هر مکعب را با مقادیر یکسان مقدار دهی می کند ، آغاز خواهیم کرد . نسخه تجدید نظر شده در ذیل نشان داده شده است :
01 /*Here , box uses a Constructor to initialize the
02 Dimensions of a box .
03 */
04 Class box {
05 Doublewidth;
06 Double height;
07 Double depth;
08 // this is the Constructor for box .
09 Box() {
10 System.out .println(“Constructing box”);
11 Width = 10;
12 Height = 10;
13 Depth = 10;
14 }
15 //compute and return volume() {
16 Return width * height*depth;
17 }
18 }
19 Class boxdemo6 {
20 Public static void main (string arg[]) {
21 // declare, allocate, and initialize box objects
22 Box mybox1 = new box ();
23 Box mybox2 = new box ();
24 Double vol;
25 // get volume of first box
26 Vol = mybox1.volume();
27 System.out.println(“volumeis” + vol);
28 // get volume of second box
29 Vol = mybox2.volume();
30 System.out.println(“volumeis” + vol);
31 }
32 }


وقتی برنامه اجرا می شود ، نتایج آن به شکل زیر خواهد بود :

Constructing box
Constructing box
Volume is 1000.0
Volume is 1000.0


Mino آنلاین نیست.   پاسخ با نقل قول
قدیمی 04-18-2012   #19
Mino
عضو تالار
 

تاریخ عضویت: Feb 2012
محل سکونت: خوزستان، اهواز،
نوشته ها: 802
تشکرهای ایشان: 22,059
33,363بار در12,628پست از ایشان تشكر شده است

صندوق مدال ها

پیش فرض


بفیه درس 10


همان گونه که ملاحظه می کنید ، mybox1 و mybox2 هر دو هنگام ایجاد به وسیله Constructor ای که box() نام دارد ، مقدار دهی شده اند . از آنجایی که Constructor ابعاد ۱۰*۱۰*۱۰ را به تمام مکعب ها نسبت می دهد ، حجم mybox1 و mybox2 برابر خواهد شد . عبارت println() در box() صرفا به خاطر نمایش صحت عملکرد آناست . بیشتر Constructor ها چیزی رانمایش نخواهند داد . آنها صرفا عمل مقدار دهی اولیه را برای شیء انجام می دهند .
پیش از ادامه کار ، عملگر new رایک مرتبه دیگر بررسی می کنیم . همان گونه که می دانید وقتی حافظه ای رابه یک شیء تخصیص می دهید ، می بایست از شکل کلی زیر استفاده کنید :1 Class-var = new classname();


اینک می توانید حدس بزنید که چرا وجود پرانتزها پس از نام کلاس ضروری است . آنچه که واقعا رخ می دهد ، آن است که Constructor کلاس فراخوانده می شود . از این رو ، در سطر زیر :
1 Box mybox1 = new box();


New box() موجب فراخوانی Constructor کلاس می شود که همنام با خود کلاس است (یعنی box()). وقتی Constructor ای را صریحا برای کلاسی تعریف نمی کنید ، جاوا این کار رابه طور پیش فرض انجام می دهد . به همین دلیل است که سطر بالا در نگارشهای پیشین مثال box ، که فاقد تعریف Constructor بودند ، به خوبی کار می کرد . Constructor پیش فرض تمام نمونه متغیرها رابه طور خودکار با صفر مقدار دهی می کند . Constructor خاص خودتان را تعریف می کنید . Constructor پیش فرض دیگر به کار برده نمی شود .
Constructor های پارامتریک
اگر چه Constructor مثال پیش (box()) عمل مقدار دهی اولیه را برای شیء box انجام می دهد ، اما چندان مفید نیست – ابعاد تمام مکعبها یکسان خواهدبود . باید به دنبال روشی برای ساخت شیء های box با ابعاد گوناگون باشیم . راه حل آسان برای انجام این کار ، افزودن پارامترهایی به Constructor است . همان گونه که احتمالا حدس زده اید ، انجام این کار موجب مفید تر شدن آن می شود . به عنوان مثال ، در نگارش جدید box ، یک Constructor پارامتریک تعریف شده است که ابعاد هر مکعب را بر اساس تعداد پارامترها تعیین می کند . به روش ایجاد شیء های box دقت نمایید .
01 /*Here , box uses a Constructor to
02 initialize the Dimensions of a box .
03 */
04 Class box {
05 Double width;
06 Double height;
07 Double depth;
08 // this is the Constructor for box .
09 Box(double w,double h, double d) {
10 Width = w;
11 Height = h;
12 Depth = d;
13 }
14 //compute and return volume
15 Double volume() {
16 Return width * height*depth;
17 }
18 }
19 Class boxdemo7 {
20 Public static void main (string args[]) {
21 // declare, allocate, and initialize box objects
22 Box mybox1 = new box (10,20,15);
23 Box mybox2 = new box (3,6,9);
24 Double vol;
25 // get volume of first box
26 Vol = mybox1.volume();
27 System.out.println(“volumeis” + vol);
28 // get volume of second box
29 Vol = mybox2.volume();
30 System.out.println(“volumeis” + vol);
31 }
32 }


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

Volume is 3000.0
Volume is 162.0

همان گونه که ملاحظه می کنید ، مقدار دهی هر شیء بر اساس پارامترهای Constructor خودش انجام می گیرد . به عنوان مثال ، در سطر زیر ،1 Box mybox1 = new box (10,20,15);


مقادیر ۱۰و۲۰و۱۵ هنگام ایجاد شیء به وسیله new به Constructor کلاس ارسال می شوند . از این رو ، مقادیر ۱۰و۲۰و۱۵ به ترتیب به width , , height depth تخصیص می یابند .
کلمه کلیدی this
گاهی اوقات متدها نیاز به ارجاع به شیئی دارند که آنها را فعال کرده است .جاوا برای فراهم ساختن این امکان ، کلمه کلیدی this را تعریف کرده است . با استفاده از this در هر متد می توان به شیء جاری ارجاع نمود . یعنی ، this همیشه ارجاع به شیئی دارد که متد برای آن فعال شده است . هر جا که ارجاع به شیئی از کلاس جاری مجاز باشد . می توان از this همیشه ارجاع به شیئی دارد که متد برای آن فعال شده است . هر جا که ارجاع به شیئی از کلاس جاری مجاز باشد ، می توان از this استفاده نمود.
برای درک بهتر اینکه this به چه چیزی ارجاع دارد ، به نگارش زیر از box() توجه کنید 1
1 //A redundant use of this.
2 Box(double w, double h, double d) {
3 This.width = w;
4 This .height = h;
5 This.depth =d;
6 }


این نگارش از box() دقیقا همچون نگارش قبلی کار می کند . استفاده از this بی مورد است ، اما کاملا صحیح است . this در این نگارش ، همیشه به شیئی که متد را فرا می خواند، ارجاع خواهد داشت . اگر چه کاربرد آن در این مثال بی مورد است ، اما در سایر موارد مفید واقع می شود . یکی از آن موارد در قسمت آتی شرح داده شده است .
پنهان کردن نمونه متغیرها
همان گونه که می دانید ، تعریف کردن دو متغیر محلی همنام در یک محدوده در جاوا غیر قانونی است . جالب است بدانید که در جاوا می توانید متغیرهای محلی ، از جمله پارامترهای نرمال متدها ، با نام های یکسان با نمونه متغیرهای کلاس ها داشته باشید . اما ، وقتی نام یک متغیر محلی با نمونه متغیری از یک کلاس یکسان می شود ، آن متغیر محلی سبب پنهان شدن نمونه متغیر همنام با خود می شود . به همین دلیل است که از width. Height , depth در کلاس bos به عنوان پارامتر های constructor (box()) استفاده نشد . اگر این گونه می شد ، در آن صورت width به پارامتر نرمال خود constructor ارجاع می کرد و نمونه متغیر width کلاس پنهان می شد. اگر چه معمولا استفاده از نامهای دیگر آسانتر است ، اما روش دیگری هم برای حل این مشکل وجود دارد . چون this به شما امکان می دهد تا مستقیما به شیء ارجاع داشته باشید ، با استفاده از آن می توانید مشکل تداخل نام در بین نمونه متغیرها و متغیرهای محلی را حل کنید . به عنوان مثال ، به نگارش دیگری از box() توجه کنید که از width. Height , depth به عنوان نام پارامترها استفاده نموده ، و سپس از this برای دستیابی به نمونه متغیرهای همنام با پارامترها استفاده می کند 1
1 //use this to resolve name-space collisions.
2 Box(double width, double height, double depth) {
3 His.width = width;
4 This.height = height;
5 This.depth = depth;
6 }


نکته ای که باید به آن توجه کنید: استفاده این گونه از this گاهی اوقات می تواند گمراه کننده باشد ، و برخی از برنامه سازان دقت می کنند تا برای متغیرهای محلی و پارامترهای نرمال از نامهایی استفاده نکنند که منجر به پنهان شدن نمونه متغیرهای کلاس شود . البته ، برخی برنامه سازان دیگر ، خلاف این امر را باور دارند – یعنی معتقدند که باید برای شفافیت بیشتر از نامهای یکسان استفاده نمود ، و برای بر طرف کردن مشکل پنهان ماندن نمونه متغیرهای کلاس ، از this استفاده کرد.
اگر چه استفاده از this در مثالهای پیش گفته چندان ارزشمند نیست ، اما در برخی شرایط بسیار مفید واقع می شود .
بازپس گیری حافظه بلا استفاده
از آنچایی که شیء ها با استفاده از عملگر new به طور پویا تخصیص می یابند ، ممکن است از خود بپرسید که چگونه از بین برده می شوند و حافظه آنها چگونه برای استفاده های آتی آزاد می شود . در برخی از زبانها ، از قبیل C++ ، شیءهایی که به طور پویا تخصیص داده می شوند را باید به صورت دستی با استفاده از عملگر delete، آزاد نمود . جاوا از رویه دیگری استفاده می کند؛ آزادسازی را به طور خودکار برایتان انجام می دهد . تکنیکی که از آن برای انجام این کار استفاده می شود ، garbage collection نام دارد . عملکرد آن به این شرح است ؛ وقتی هیچ گونه ارجاعی به یک شیء وجود نداشته باشد ، فرض می شود که شیء دیگر مورد نیاز نبوده و حافظه آن نیز با پس گرفته می شود . در زبان جاوا ، برخلاف c++ دیگر نیازی به از بین بردن شیء ها نیست . این تنها به صورت نامنظم و گاه و بیگاه در طی اجرای برنامه انجام می شود . انجام آن صرفا به خاطر عدم نیاز به یک یا چند شیء صورت نمی گیرد . به علاوه ، نسخه های مختلف محیط اجرای جاوا ، رویه های مختلفی برای انجم این کار دارند ، اما آنچه لازم است بدانید ، آن است که هنگام نوشتن برنامه ها لازم نیست نگران این مسئله باشید.
متد finalize()
گاهی اوقات برخی از شیءها نیاز به انجام عملیات خاص پیش از از بین بردن دارند . به عنوان مثال ، اگر شیئی از منابع غیر جاوا، از قبیل handle یک فایل یا فونت خاص ، استفاده می کند ، در آن صورت بهتر است پیش از آزاد سازی آن شیء از آزاد شدن آن منابع اطمینان حاصل نمایید . جاوا برای مدیریت این گونه شرایط، مکانیزمی به نام finalization دارد . با استفاده از این مکانیزم می توانید عملیات خاصی را مشخص کنید تا درست پیش از آزاد سازی یک شیء ، تماما انجام شوند .
برای پیاده سازی این مکانیزم در هر کلاس ، کافی است متد finalize() راتعریف کنید . محیط زمان اجرای جاوا این متد را هنگام بازیافت شیئی از آن کلاس فرا می خواند . در متد finalize() باید آن عملیاتی را مشخص کنید که باید پیش از از بین بردن یک شیء انجام شوند . قسمتی که مسئولیت بازپس گیری حافظه بلااستفاده را دارد ، به طور متناوب اجرا شده و شیء هایی را جستجو می کند که دیگر ارجاعی به آنها صورت نمی گیرد و به طور غیر مستقیم نیز از طریق سایر شیءها به آنها ارجاع نمی شود . درست پیش از آزاد کردن هر شیء ، سیستم «زمان اجرای» جاوا متد finalize() را برای آن شیء فرا می خواند .
شکل کلی این متد در زیر نشان داده شده است 1
1 Protected void finalize()
2 {
3 // finalization code here
4 }


کلمه کلیدی protected، مشخصه ای است که از دستیابی به finalize() توسط روتین های خارج از همان کلاس جلوگیری می کند . این مشخصه و سایر مشخصه های دستیابی در فصل ۷ تشریح شده اند .
مهم است بدانید که finalize() تنها پیش از بازپسگیری حافظه شیء ها فراخوانده می شود . مثلا زمانی که یک شیء در خارج از محدوده اش قرار میگیرد ، این متد فراخوانده نمی شود . این بدین معناست که هیچگاه نمی توانید تشخیص دهید که finalize() چه وقت اجرا خواهدشد – یا حتی اینکه اصلا فراخوانده خواهد شد یا خیر . بنابراین ، برنامه تان باید روشهای دیگری برای آزاد سازی منابع (وغیره) مورد استفاده شیء فراهم کند . یعنی ، برنامه تان نباید برای عملیات متعارف به این متد اتکا داشته باشد .
توجه : اگر با C++ آشنایی داشته باشید ، در آن صورت می دانید که C++ امکان تعریف destructor را برای هم کلاس فراهم میکند . destructor زمانی فراخوانده یم شود که شیء خارج از محدوده قرار می گیرد . جاوا از این ایده پشتیبانی نمی کند و امکان نوشتن destructorها را نیز فراهم فراهم نساخته است . متد finalize() وظیفه destructor ها را به طور تقریبی انجام می دهد . به مرور که تجربه بیشتری در خصوص کار با جاوا کسب می کنید ، خواهید دید که نیاز به عملیات destructor ها به دلیل سیستم «باز پس گیری حافظه بلا استفاده » در جاوا کمینه شده است .
کلاس stack

اگر چه کلاس box برای نشان دادن عناصر پایه یک کلاس مفید است ، اما در عمل ارزش چندانی ندارد . این فصل را برای نشان دادن قدرت واقعی کلاس ها ، با ارائه مثال پیچیده تری به پایان می رسانیم . همان گونه که احتمالا از بحث برنامه سازی شیء گرا (OPP) در فصل ۲ به یاد دارید ، یکی از مهمترین مزایای opp، نهان سازی داده ها و روتین هایی است که آنها را پردازش و مدیریت می کنند . همان گونه که دیده اید ، «کلاس» مکانیزمی است که نهان سازی در جاوا از طریق آن تحقق می یابد . وقتی کلاسی را ایجاد می کنید ، در واقع نوع جدیدی از داده ها ایجادمی شود که هم ماهیت داده ها را تعریف می کند ، و هم روتین هایی که برای پردازش و مدیریت آنها مورد استفاده قرار می گیرند . افزون بر این متدها ، رابط یکپارچه و تحت کنترلی را برای داده های کلاس تعریف می کنند . از این رو ، بی آنکه نگران جزئیات پیاده سازی کلاس یا چگونگی مدیریت داده های درون آن باشید ، به راحتی می توانید کلاس را از طریق متدهایش به کار برید . کلاس ها از یک جهت ، «موتور داده ها » هستند . برای به کارگیری موتور از طریق اقلام کنترل کننده آن ، نیازی به داشتن اطلاعات درباره داخل موتور نیست . در حقیقت ، از آنجایی که جزئیات پنهان می شوند ، عملیات داخلی را می توان متناسب با نیازها تغییر داد . تا زمانی که برنامه تان کلاس را از طریق متدهایش به کار برد ، جزئیات داخلی را می توان بدون تاثیرات جانبی بر خارج کلاس تغییر داد .
برای آنکه با یکی از کاربردهای عملی بحث بالا آشنا شوید ، اینک یکی از مثالهای قدیمی نهان سازی را پیاده سازی می کنیم . پشته . هر پشته ، داده ها را با استفاده از ترتیب “FILO” (First In , First Out) ذخیره می کند . یعنی ، هر پشته همچون یک دسته بشقاب بر روی یک میز است – نخستین بشقابی که بر روی میز قرار می گیرد ، آخرین بشقابی است که مورد استفاده قرار می گیرد . پشته ها از طریق دو عملی که از ابتدا “Push” و “Pop” نامیده شده اند کنترل می شوند . برای قرار دادن هر عنصر جدید بر روی پشته ، از “Push” استفاده می شود . برای برداشتن اقلام نیز از “Pop” نامیده شده اند کنترل می شوند . برای قراردادن هر عنصر جیدید بر روی پشته ، از “Push” استفاده می شود . برای برداشتن اقلام نیز از “Pop” نامیده شده اند کنترل می شوند . برای قرار دادن هر عنصر جدید بر روی پشته ، از “Pop” استفاده می شود . برای برداشتن اقلام نیز از “Pop” استفاده می شود. همان گونه که خواهید دید ، نهان سازی کل مکانیزم پشته آسان است .
کلاس زیر که Stack نامیده شده است ، پشته ای از اعداد صحیح را پیاده سازی می کند :
01 // this class defines an integer stack that can hold 10 values .
02 Class stack {
03 Int stack[] = new int[10];
04 Int tos;
05 // Intialize top-of-stack
06 Stack() {
07 Tos = -1
08 }
09 // push an item onto the stack
10 Void push (int item) {
11 If(tos==9)
12 System.out.println(“stack is full.”);
13 Else
14 Stack[+tos] = item;
15 }
16 // pop an item from the stack
17 Int pop() {
18 If (tos<0) {
19 System.out.println(“stack undeflow.”);
20 Return 0;
21 }
22 }


همان گونه که ملاحظه می کنید ، در کلاس stack دو آیتم داده ای و سه متد تعریف شده است . پشته اعداد صحیح به وسیله آرایه stack نگهداری می شود . از متغیر tos به عنوان شاخص این آرایه استفاده می شود که همیشه حاوی شاخص بالاترین عنصر پشته است . مقدار اولیه ۱٫ توسط stack() (constructor کلاس) به tos تخصیص می یابد که نشانگر یک پشته خالی است . متد Push() ، آیتم جدید را بر روی پشته قرار می دهد . برای بازیابی هر یک از آیتم ها نیز ، Pop() فراخواندهمی شود . چون دستیابی به پشته از طریق Push() و Pop() صورت می گیرد ، اینکه پشته در یک آرایه نگهداری می شود ، واقعا هیچ ارتباطی به استفاده از آن ندارد . به عنوان مثال ، پشته را می شد در ساختار داده ای پیچیده تری چون فهرستهای زنجیره ای نگهداری نمود ، و در عین حال دو رابط push() و Pop() صورت می گیرد ، اینکه پشته دریک آرایه نگهداری می شود ، واقعا هیچ ارتباطی به استفاده از آن ندارد . به عنوان مثال ، پشته را می شد در ساختار داده ای پیچیده تری چون فهرستهای زنجیره ای نگهداری نمود ، و در عین حال دو رابط Push() و Pop() را به همین صورت حفظ کرد .
کلاس TestStack ای که در ذیل نشان داده شده است ، عملکرد کلاس Stack را نشان می دهد . دو پشته از اعداد صحیح ایجاد می شود ، مقادیری به هر یک از آنها افزوده می شود ، و سپس از روی پشته برداشته می شوند.
01 Class TestStack {
02 Public static void main (string arg[]) {
03 Stack mystack1 = new stack();
04 Stack mystack2 = new stack ();
05 // push some numbers onto the stack
06 For(int i=0; i<10; i++) mystack1.push(i);
07 For(int i=10; i<20; i++) mystack2.push(i);
08 // pop those numbers off the stack
09 System.out.println(“stack in mystack1:”);
10 For (int i=0; i<10; i++)
11 System .out.println(mystack1.pop());
12
13 System.out.println(“stack in mystack2:”);
14 For (int i=0; i<10; i++)
15 System.out.println(mystack2.pop());


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

Stack in mystack1:
9876543210
Stack in mystack2:
19 18 17 16 15 14 13 12 11 10

همان گونه که می بینید ، محتوای هر یک از پشته ها ، جدای از دیگری است .
واپسین نکته درباره کلاس stack : آرایه ای که برای نگهداری پشتهبه کار می رود (stack) ، با به کارگیری روش پیاده سازی مثال بالا ، از خارج از کلاس stack قابل تغییر خواهد بود . این امر موجب استفاده نادرست یا مخرب از stack خواهد شد .
Mino آنلاین نیست.   پاسخ با نقل قول
پاسخ


کاربران در حال دیدن موضوع: 1 نفر (0 عضو و 1 مهمان)
 

(View-All تعداد کاربرانی که این تاپیک را مشاهده کرده اند : 4
eliias, Mino, sahel110, y@lda
ابزارهای موضوع
نحوه نمایش

مجوز های ارسال و ویرایش
شما نمیتوانید موضوع جدیدی ارسال کنید
شما امکان ارسال پاسخ را ندارید
شما نمیتوانید فایل پیوست در پست خود ضمیمه کنید
شما نمیتوانید پست های خود را ویرایش کنید

BB code هست فعال
شکلک ها فعال است
کد [IMG] فعال است
کد HTML غیر فعال است

انتخاب سریع یک انجمن


اکنون ساعت 05:12 برپایه ساعت جهانی (GMT - گرینویچ) +3.5 می باشد.


Powered by vBulletin Version 3.8.9
.Copyright ©2000 - 2017, Jelsoft Enterprises Ltd

Free Persian Language By Persian Forum Ver 3.0
« ثبت شده در پایگاه ساماندهی وزارت ارشاد »
مسئولیت متون درج شده در این پایگاه اینترنتی، بر عهده ی نویسنده ی آن می باشد.