قلمرو زمان حيات متغيرها در جاوا

قلمرو زمان حيات متغيرها در جاوا

يك متغير به وسيله تركيبي از يك شناسه ، يك نوع و يك مقدار دهی اوليه اختياري تعريف خواهد شد. علاوه بر اين ، كليه متغيرها داراي يك قلمرو هستند كه رويت پذيري آنها را تعريف مي‌كند و يك زمان حيات نيز دارند. يك بلوك با يك ابرو باز و يك ابرو بسته محصور مي شود و يك بلوك تعريف كننده يك قلمرو است. بدين ترتيب هر بار كه يك بلوك جديد را شروع مي كنيد ، يك قلمرو جديد نيز بوجود مي آوريد. يك قلمرو (scope) تعيين كننده آن است كه چه اشيائي براي ساير بخش‌هاي برنامه قابل رويت هستند. اين قلمرو همچنين زمان حيات (lifetime) آن اشيا را تعيين مي كند.

اكثر زبان‌هاي كامپيوتري دو طبقه بندي از قلمروها را تعريف مي كنند : سراسري (global) و محلي (local).
اما اين قلمروهاي سنتي بخوبي با مدل موكد شیء گرايي جاوا مطابقت ندارند. اگر چه در جاوا هم مي توان مقاديري را به عنوان قلمرو سراسري ايجاد نمود، اما اين فقط يك نوع استثناء است و عموميت ندارد. در جاوا قلمرو اصلي همان‌هايي هستند كه توسط يك كلاس يا يك روش تعريف مي شوند. حتي همين تمايز نيز تا حدي ساختگي و مصنوعي است. اما از آنجايي كه قلمرو كلاس داراي مشخصات و خصلت‌هاي منحصر بفردي است كه قابل استفاده در قلمرو تعريف شده توسط روش نيست ، اين تمايز تا حدي محسوس خواهد بود. در حال حاضر فقط قلمروهاي تعريف شده توسط يك روش يا داخل يك روش را بررسي مي كنيم. قلمرو تعريف شده توسط يك روش با يك ابروي باز شروع مي شود. اما اگر آن روش داراي پارامترهايي باشد ، آنها نيز داخل قلمرو روش گنجانده خواهند شد.

بعنوان يك قانون عمومي ، متغيرهاي اعلان شده داخل يك قلمرو براي كدهايي كه خارج از قلمرو تعريف مي شوند ، قابل رويت نخواهند بود (قابل دسترسي نيستند). بدين ترتيب ، هنگامي كه يك متغير را درون يك قلمرو اعلان مي كنيد، در حقيقت آن متغيیر را محلي دانسته و آن را در مقابل دستيابي‌ها و تغييرات غير مجاز محافظت مي‌كنيد. در حقيقت، قوانين قلمرو اساس كپسول سازي را فراهم مي كنند. قلمروها را مي توان بصورت تودرتو (nesting) محفوظ داشت. بعنوان مثال ، هر زمان يك بلوك كد ايجاد كنيد ، يك قلمرو جديد تودرتو ايجاد نموده ايد. هنگامي كه اين واقعه روي مي دهد ، قلمرو بيروني ، قلمرو دروني را دربر مي‌گيرد. اين بدان معني است كه اشياء اعلان شده در قلمرو بيروني براي كدهاي داخل قلمرو دروني قابل رويت هستند اما عكس اين قضيه صادق نيست. اشياء اعلان شده داخل قلمرو دروني براي بيرون قلمرو قابل رويت نخواهند بود.

برنامه ای برای درک تأثیر قلمروهای تودرتو

// Demonstrate block scope.
class Scope {
public static void main(String args[] ){
int x; // known to all code within main
x = 10;
if(x == 10 ){ // start new scope
int y = 20; // known only to this bock
// x and y both known here.
System.out.println("x and y :" + x + " " + y);
x = y * 2;
}
// y = 100 :// Error! y not known here
// x is still known here.
System.out.println("x is " + x);
}
}

همانطوري كه توضيحات نشان مي دهند ، متغير x در ابتداي قلمروي ()main اعلان شده و براي كليه كدهاي متعاقب داخل ()main قابل دسترسي مي باشد. داخل بلوك if متغير y اعلان شده است. از آنجايي كه يك بلوك معرف يك قلمرو است، y فقط براي ساير كدهاي داخل بلوك خود قابل رويت است. اين دليل آن است كه خارج بلوك مربوطه، خط y=100 در خارج توضيح داده شده است. اگر نشانه توضيح راهنمايي را تغيير مكان دهيد ، يك خطاي زمان كامپايل (compile-time error) اتفاق مي افتد چون y براي بيرون از بلوك خود قابل رويت نيست. داخل بلوك if متغير x قابل استفاده است زيرا كدهاي داخل يك بلوك ( منظور يك قلمرو تودرتو شده است ) به متغيرهاي اعلان شده در يك قلمرو دربرگيرنده دسترسي دارند. داخل يك بلوك ، در هر لحظه اي مي توان متغيرها را اعلان نمود ، اما فقط زماني معتبر مي شوند كه اعلان شده باشند . بدين ترتيب اگر يك متغير را در ابتداي يك روش اعلان مي كنيد، براي كليه كدهاي داخل آن روش قابل دسترس خواهد بود. بالعكس اگر يك متغير را در انتهاي يك بلوك اعلان كنيد ، هيچ فايده اي ندارد چون هيچ يك از كدها به آن دسترسي ندارند .

یک قطعه برنامه نا معتبر

// This fragment is wrong!
count = 100; // oops! cannot use count before it is declared!
int count;

اين قطعه برنامه غير معتبر است چون نمي توان از count قبل از اعلان آن استفاده نمود.

يك نكته مهم ديگر در اينجا وجود دارد كه بايد بخاطر بسپاريد.

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

برنامه زير را در نظر بگيريد

// Demonstrate lifetime of a variable.
class LifeTime {
public static void main(String args[] ){
int x;
for(x = 0; x < 3; x++ ){
int y =- 1; // y is initialized each time block is entered
System.out.println("y is :" + y); // this always prints- 1
y = 100;
System.out.println ("y is now :" + y);
}
}
}

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

y is- :1
y is now:100
y is- :1
y is now:100
y is- :1
y is now:100

همانطوري كه مشاهده مي كنيد ، هر بار كه به حلقه for داخلي وارد مي شويم ، y همواره بطور مكرر مقدار اوليه 1- را اختيار مي كند. اگر چه بلافاصله به اين متغير مقدار 100 نسبت داده مي شود، اما هر بار نيز مقدار خود را از دست مي‌دهد.

اگر چه مي‌توان بلوك‌ها را تودرتو نمود، اما نمي توانيد متغيري را اعلان كنيد كه اسم آن مشابه اسم متغيري در قلمرو بيروني باشد. از اين نظر جاوا با زبانهاي C و ++C متفاوت است

برنامه زیر را در نظر بگیرید

// This program will not compile
class ScopeErr {
public static void main(String args[] ){
int bar = 1;
{ // creates a new scope
int bar = 2; // Compile-time error -- bar already defined!
}
}
}

برنامه ای كه در آن تلاش شده تا دو متغیير جدا از هم با اسم اعلان شوند. در جاوا اينكار مجاز نيست اما در C و ++C اين امر مجاز بوده و دو bar كاملاً جدا خواهند ماند



نظرات کاربران



عبارت امنیتی : حاصل 7 × 5 می شود :
متن پیام :