استفاده از کلمه ی کلیدی this در جاوا
وقتی که دارید کلاس ها را ایجاد می کنید، آنها به سرعت می توانند بزرگ و بزرگتر شوند.
در کنار متغیرهای عضوی، هر کلاس حاوی چند متد است و ممکن است هریک از این متدها، تعدادی overload داشته باشند.
وقتی که از یک کلاس، یک شیء نمونه گیری می کنیم، برای هر متغیر نمونه(instance field) فضایی در حافظه در نظر گرفته می شود. بعنوان مثال، اگر یک کلاس حاوی 20 متغیر نمونه باشد، وقتی که از آن یک شیء ایجاد کنیم، مقدار کافی از حافظه برای نگهداری مقادیر 20 متغیر در نظر گرفته می شود. حالا اگر از همین کلاس 200 شیء ایجاد کنیم، مقداری حافظه برای نگهداری مقادیر 4000 متغیر نمونه در نظر گرفته خواهد شد(20 متغیر ضرب در 200 شیء).
معمولا ما می خواهیم که هر نمونه از کلاس، دارای متغیرهای نمونه ی مخصوص به خودش باشد. وقتی که می خواهیم هر شیء یک متغیر نمونه ی مخصوص به خودش داشته باشد، نباید این متغیر را از نوع static تعریف کنیم. اما وقتی که برای یک کلاس، یک متد ایجاد کنیم، هر شیء ای می تواند از این متد استفاده کند.
وقتی که می خواهیم از یک متد غیر استاتیک استفاده کنیم، ابتدا نام شیء را می نویسیم و سپس یک نقطه می گذاریم و پس از آن نام متد را می نویسیم، درست مانند مثال های زیر:
مثال
aWorker.getEmpNum()
anotherWorker.getEmpNum()
بنابراین وقتی که متد ()getEmpNum را اجرا کنیم، در حقیقت تنها نمونه ی موجود از این متد را اجرا می کنیم. اما وقتی که در داخل متد ()getEmpNum می خواهیم به متغیر empNum دسترسی داشته باشیم، بر اساس شیء مورد نظر، به یک متغیر متفاوت دسترسی خواهیم داشت.ما باید برای کامپایلر معلوم کنیم که می خواهیم از کدام مقدار متغیر empNum در این متد استفاده کنیم. یعنی می خواهیم متد()getEmpNum کدام مقدار متغیر empNum را برای ما برگرداند.
اما کامپایلر خودش قادر است تا به متغیر شیء مورد نظر به درستی دسترسی داشته باشد، زیرا هر موقع که ما یک متد غیراستاتیک را فراخوانی می کنیم، به طور غیر مستقیم، یک ارجاع(reference ) به آن شیء نام گذاری شده که به متد مورد نظر متصل شده است، ارسال می کنیم. این ارجاع در حقیقت آدرسِ شیء مورد نظر در حافظه است.به این ارجاع، غیر مستقیم می گوییم، زیرا به طور اتوماتیک فهمیده می شود و نیازی نیست که ما آن را بنویسیم.
اگر بخواهیم به یک متد غیر استاتیک که در یک شیء قرار دارد، رجوع کنیم، از مرجع this استفاده می کنیم. کلمه ی کلیدی this یکی از کلمات رزرو شده در جاوا است.
بعنوان مثال به دو متد نشان داده شده در تصویر 4.21 که کار یکسانی انجام می دهند توجه کنید. اولین متد، به طور غیر مستقیم از مرجع this استفاده می کند. اما دومین متدبه طور صریح از مرجع this استفاده می کند. هر دوی این متدها، مقدار متغیر empNum از یک شیء را برمی گردانند.
(شماره 1: مرجع this به صورت یک پارامتر، به هردوی این متدهای غیر استاتیک به طور اتوماتیک ارسال می شود و نیازی نیست شما این کار را انجام دهید)
ما غالبا نیازی نداریم تا از مرجع this در داخل متدهایی که می نویسیم استفاده کنیم. اما به یاد داشته باشید که مرجع this همواره وجود دارد و به وسیله ی آن می توان به متغیر نمونه ی شیء مناسب دسترسی پیدا نمود.
نکته: تنها متدهای غیر استاتیک مرجع this را دریافت می کنند.
در برخی موارد ما باید از مرجع this برای اینکه کلاس های ما به درستی کار کنند، استفاده کنیم. در تصویر 4.22 یک مثال نشان داده شده است.
در داخل constructor این کلاس،نام پارامترهای stuNum و gpa با نام متغیرهای عضوی درون این کلاس یکسان هستند. در داخل این constructor، پارامترهای stuNum و gpa به متغیرهای محلی اشاره می کنند نه به متغیرهای عضوی درون این کلاس. دستور stuNum = stuNum کاری انجام نمی دهد و فقط مقدار خودش را در خودش ذخیره می کند.
اپلیکیشن 4.23 تلاش می کند تا یک شیء از نوع Student با آرگومان های 111 و 3.5 ایجاد کند. اما در تصویر 4.24 یک خروجی اشتباه را مشاهده می کنیم. مقادیر ما به متغیرهای عضوی انتساب داده نشده اند و این متغیرها تنها برابر با 0 شده اند.
(شماره 1: تمام چهار متغیر استفاده شده در این دو عبارت، متغیرهایی محلی هستند که در داخل لیست پارامترهای این سازنده، تعریف شده اند. بنابراین متغیرهای عضوی این کلاس در دسترس نیستند و این دستورات هیچ کاری را انجام نمی دهند).
تصویر 4.25 کلاس Student را به صورت اصلاح شده، نشان می دهد. تنها تفاوت بین این کلاس و کلاس تصویر 4.22 این است که در عکس 4.22 در داخل constructor از مرجع this استفاده نشده است اما در عکس 4.25 از مرجع this استفاده شده است. وقتی از مرجع this در داخل یک متد از یک کلاس، برای یک متغیر استفاده می کنیم، مرجع this به جای اشاره به متغیر درون متد، به متغیر عضوی درون کلاس اشاره می کند.
حالا وقتی که اپلیکیشن TestStudent از این نسخه ی جدید کلاس Student استفاده کند، خروجی صحیحی ایجاد می شود که در تصویر 4.26 نشان داده شده است:
استفاده از مرجع this در constructorها
فرض کنید یک کلاس به نام student ساخته ایم، و یک متغیر عضوی برای نگهداری شماره ی دانش آموز و یک متغیر عضوی دیگر برای نگهداری معدل دانش آموز در آن قرار داده ایم. همچنین فرض کنید که به چهار constructor که overload شده اند، به صورت زیر نیاز داریم:
- یک constructor که یک مقدار int و یک مقدار double را می پذیرد و آنها را به ترتیب به متغیر شماره ی دانش آموز و متغیر معدل دانش آموز انتساب می دهد.
- یک constructor که یک مقدار double را می پذیرد و آن را به متغیر معدل دانش آموز انتساب می دهد. و شماره ی هر دانش آموز با مقدار 999 مقداردهی اولیه می شود.
- یک constructor که یک مقدار int را می پذیرد و آن را به متغیر شماره ی دانش آموز انتساب می دهد. و مقدار معدل هر دانش آموز با مقدار 0.0 مقداردهی اولیه می شود.
- یک constructor پیش فرض که مقدار 999 را به متغیر شماره ی دانش آموز انتساب می دهد و مقدار 0.0 را به متغیر معدل دانش آموز انتساب می دهد.
عکس 4.27 این کلاس را نشان می دهد. با اینکه این کلاس به خوبی کار می کند و اشیاء Student را به چهار روش متفاوت تولید می کند، اما در داخل این constructor تکرارهای زیادی وجود دارد:
شما می توانید کدهای عکس 4.27 را با فراخوانی یک constructor در داخل دیگر constructorها موثر تر کنید و خطاپذیری آنها را کمتر کنید. برای انجام این کار، با استفاده از مرجع this از یک constructor یک نسخه ی دیگر از constructorها را فراخوانی می کنیم. بنابراین کدهای تصویر 4.27 را می توانیم به صورت تصویر 4.28 بازنویسی کنیم.
با انجام این کار، در داخل constructor های غیر اصلی، constructor اصلی را فراخوانی می کنیم. این کار باعث می شود که کدنویسی ما کمتر شود و احتمال خطا کاهش یابد.
نکته: شما نمی توانید دستور ()this را در داخل دیگر متدهای یک کلاس فراخوانی کنید. تنها می توانید آن را در داخل constructorها فراخوانی کنید. اگر دستور ()this را در یک constructor فراخوانی کنید، باید اولین دستور از این constructor باشد.
- نوشته شده توسط احسان عباسی
- بازدید: 6673