هر آنچه که تا این مرحله از کار فرا گرفته ایم بیشتر تئوریک بوده تا عملی. در این آموزش قصد داریم تا مفاهیم شیء گرایی، اصول ساخت کلاس و آبجکت و همچنین طراحی یو ام ال که تا این مرحله فرا گرفتیم را به صورت عملی تبدیل به کدهای واقعی با استفاده از یک زبان شیء گرا همچون جاوا نماییم. برای شروع، یو ام ال کلاسی تحت عنوان Spaceship به معنی «سفینه» را در نظر میگیریم که برای ساخت یک بازی جنگی مورد استفاده قرار خواهد گرفت:
این کلاس از دو Attribute تحت نام های name و shieldStrength برخوردار است که name قابل روئیت هم از داخل این کلاس و هم توسط سایر آبجکت ها است که نوع آن هم از جنس استرینگ است. Attribute دوم از جنس عدد صحیح است و با توجه به این که علامت – در کنار نامش قرار گرفته، این بدان معنا است که این Attribute صرفاً از داخل این کلاس قابل روئیت می باشد. name محلی برای ذخیره سازی نام سفینه است. shieldStrength هم که به معنی «میزان قدرت محافظ سفینه» است، محلی برای ذخیره سازی داده ای از جنس عدد صحیح است که با تغییر این داده، میتوان توان محافظتی سفینه را کم یا زیاد کرد.
در بخش متدها نیز دو متد تحت عناوین ()fire و ()reduceSheilds داریم که داده ی خروجی متد اول داده ای از جنس استرینگ است یا بهتر بگوییم متد اول داده از از جنس استرینگ را return میکند یا «باز می گرداند» و متد دوم هم برای این که وظیفهاش را انجام دهد، نیاز به یک داده ی ورودی از جنس عدد صحیح یا Integer دارد و این در حالی است که این متد هیچ چیزی را return نخواهد کرد. لازم به ذکر است که هر دوی این متدها قابل روئیت هم از داخل این کلاس و هم توسط سایر آبجکت ها می باشند. سورس کد یو ام ال فوق در زبان برنامه نویسی جاوا به صورت زیر خواهد بود:
public class Spaceship {
public String name;
private int shieldStrength;
public String fire() {
return "Boom!";
}
public void reduceShields(int amount) {
shieldStrength -= amount;
}
}
همانطور که در کد فوق ملاحظه می شود، برای ساخت کلاس از کلیدواژگان public class استفاده نموده سپس نام کلاس که در اینجا Spaceship است را قرار داده ایم و مقابل آن یک جفت علامت { } قرار داده ایم. هر آنچه که مابین علامت های { } قرار گیرد، از این پس متعلق به کلاس Spaceship خواهد بود.
سپس اقدام به ساخت Attribute ها کردهایم که پیش از این هم گفتیم که نوع Attribute یی تحت عنوان name استرینگ است و این در حالی است که این Attribute قرار است تا از همه جای برنامه قابل روئیت باشد. پس ابتدا کلیدواژه ی public که معادل علامت + در یو ام ال است را نوشته، سپس نوع آن را با نوشتن String مشخص میکنیم و در نهایت نامی برای آن در نظر میگیریم که در این مثال name است. پس از تعریف کردن یک نام، حال نوبت به ایجاد shieldStrength میرسد که از جنس عدد صحیح است پس از Data Type یا «نوع داده» ای از جنس int یا «عدد صحیح» استفاده کرده و از آنجا که در یو ام ال علامت – مقابل این Attribute قرار گرفته بود، در زبان برنامه نویسی جاوا برای ایجاد این محدودیت روئیت از کلیدواژه ای تحت عنوان private استفاده می کنیم.
حال نوبت به نوشتن متدهای این کلاس می رسد. با توجه به این که متد ()fire قرار است تا از هر جای برنامه قابل روئیت باشد، ابتدا کلیدواژه ی public را نوشته سپس نوع این متد را مشخص میکنیم که استرینگ است و پس از آن نامی همچون fire به معنی «آتش زدن» در نظر میگیریم و پس از علامت های () یک جفت علامت { } قرار میدهیم که کلیه ی کدهای مربوط به این متد، داخل علامت های { } قرار خواهند گرفت. با توجه به این که متد ()fire در یو ام ال دارای هیچ گونه پارامتر ورودی نبود، داخل پرانتزهای متد fire را خالی می گذاریم. در یو ام ال مشخص کرده بودیم که این متد می بایست دادهای از جنس استرینگ را return کند. برای این منظور، داخل علامت های { } کلیدواژه ی return را نوشته و مقابل آن استرینگی تحت عنوان "!Boom" را داخل علامت های دابل کوتیشن قرار میدهیم چرا که در یو ام ال گفتیم این متد می بایست دادهای از جنس استرینگ را باز گرداند.
در ادامه ی کار، نوبت به تعریف کردن متد دوم تحت عنوان reduceSheild می رسد. این متد قرار است از همه جای برنامه قابل روئیت باشد پس ابتدا کلیدواژه ی public را نوشته سپس از آن جا که این متد قرار نیست تا هیچ نتیجهای را باز گرداند، پس کلیدواژه ی void را نوشته سپس نام متد را می نویسیم. پیش از این در طراحی یو ام ال گفتیم که این متد ابتدا به ساکن برای اجرا نیاز به یک پارامتر ورودی از جنس عدد صحیح دارد. پس ابتدا نوع این پارامتر را از طریق کلیدواژه ی int مشخص کرده سپس نامی همچون amount به معنی «مقدار» برای آن در نظر می گیریم. علامت های { } را قرار داده و داخل آن ها صرفاً یک دستور بیشتر نمینویسیم که عبارت است از مساوی قرار دادن مقدار amount با متغیر shieldStrength با این توضیح که در هر بار اجرای این متد، به خاطر وجود علامت – قبل از علامت = یک واحد از مقدار shieldStrength کم خواهد شد.
در این مرحله از آموزش، موفق شدهایم تا یک یو ام ال را به یک کلاس واقعی در زبان محبوب جاوا مبدل سازیم. همانطور که پیش از این توضیح دادیم، کلاسها چیزهایی مفهومی و انتزاعی هستند و تا زمانی که یک آبجکت یا بهتر بگوییم «نمونه ای» از روی آنها ایجاد نکنیم، این کلاس وجود خارجی نخواهد داشت. در بسیاری از زبانهای برنامه نویسی شیء گرا همچون جاوا، پی اچ پی، سی شارپ، سی پلاس پلاس و …، از کلیدواژه ی new به معنی «جدید» برای ساخت آبجکتی از روی یک کلاس استفاده می شود. پیش از این که با نحوه ی ساخت آبجکت ها از روی یک کلاس همچون کلاس Spaceship آشنا شویم، نیاز است تا با مفهوم Constructor (کانستراکتور) در زبانهای برنامه نویسی شیء گرا آشنا شویم.
به طور کلی، کانستراکتور یک نوع خاصی از متدها در زبانهای برنامه نویسی شیء گرا است که داخل کلاسها نوشته میشود تا با استفاده از آن بتوان یک آبجکت ساخت و این در حالی است که به محض ساختن یک آبجکت از روی کلاسی خاص، کانستراکتور به صورت خودکار Call یا «فراخوانی» می شود.
حال ممکن است این سؤال برای برنامه نویسان مبتدی پیش بیاید که آیا نوشتن کانستراکتور در کلاسها اجباری است؟ و آیا بدون برخورداری از کانستراکتور، نمیتوان آبجکت ساخت؟ در پاسخ به سؤال اول بایستی گفت که خیر، برای استفاده از کانستراکتور هیچ اجباری در کار نیست و در پاسخ به سؤال دوم هم بایستی گفت آری، بدون کانستراکتور هم میتوان آبجکت ساخت. اما کانستراکتورها در زبانهای برنامه نویسی شیء گرا ابداع شدهاند تا کار برنامه نویس را سادهتر کنند! برای روشنتر شدن این مسأله، به کلاس Spaceship باز می گردیم. برای ساخت یک آبجکت از روی این کلاس در زبان جاوا، کدهای زیر را میتوان نوشت:
Spaceship shahab = new Spaceship();
همانطور که در کد فوق مشاهده می شود، برای ساخت یک آبجکت یا «شیء» از روی کلاسی خاص در زبان برنامه نویسی جاوا، ابتدا نام کلاس را نوشته سپس نامی همچون «شهاب» برای آن در نظر میگیریم یک علامت = قرار داده، کلیدواژه ی new را نوشته سپس نام کلاس مد نظر را به صورت ()Spaceship می نویسیم و در نهایت یک علامت ; قرار میدهیم تا Statement یا «دستور» ما تکمیل شود.
به نظر شما آبجکتی که هماکنون ساختیم چه وضعیتی دارا است؟ به عبارت دیگر، Attribute های name و shieldStrength که در کلاس تعریف کردیم، در آبجکت shahab دارای چه مقادیر اولیهای هستند؟ در پاسخ به این سؤال بایستی گفت که این Attribute ها تهی هستند. در واقع، این شیء وجود خارجی دارد اما این در حالی است که توخالی می باشد.
Cosntructor (کانستراکتور به معنی تحت الفظی سازنده) در چنین شرایطی به داد برنامه نویسان می آید. در واقع، ما با استفاده از کانستراکتورها خواهیم توانست به محض ایجاد یک شیء جدید، آن را به صورت خودکار مقدار دهی کنیم تا وضعیت آبجکت ما از حالت تهی خارج گشته و آبجکت ساخته شده را بتوان به سادگی مورد استفاده قرار داد. در واقع، کانستراکتورها این تضمین را ایجاد میکنند که به محض ساخت آبجکتی از روی یک کلاس خاص، Attribute های آن کلاس با مقادیر مناسب پر خواهند شد. برای ساخت کانستراکتور در زبانی همچون جاوا، صرفاً نیاز است تا متدی هم نام با کلاس مد نظر ایجاد کرده و Attribute ها را در آن مقدار دهی کرد:
public class Spaceship {
public String name;
private int shieldStrength;
public Spaceship() {
name = "Shahab";
shieldStrength = 100;
}
}
همانطور که در کد فوق ملاحظه می شود، متدی از جنس public با نام Spaceship نوشته و در آن مقداری همچون "Shahab" را برای name و مقدار 100 را برای shieldStrength در نظر گرفته ایم. حال اگر همچون مراحل قبل، اقدام به ساخت یک آبجکت جدید از روی کلاس Spaceship نماییم، این آبجکت به هیچ وجه تهی نبوده و این آبجکت را میتوان مورد استفاده قرار داد چرا که کانستراکتور که این وظیفه را داشت تا به محض ساخت یک آبجکت از روی کلاس Spaceship به صورت خودکار اجرا شود، اجرا گردیده و دستورات داخلش که همان مقدار دهی Attribute های name و shieldStrength بوده را به درستی انجام داده است. به عبارت دیگر، از این پس، آبجکت ما که shahab بود، مقدار Attribute مرتبط با name آن مقداری همچون Shahab داشته و میزان قدرت محافظتی آن برابر با 100 است. در یو ام ال، اگر در بخش متدها دیدید که متدی هم نام با کلاس مد نظر نوشته شده است، آن متد کانستراکتور است:
توجه داشته باشیم که کانستراکتورها میتوانند پارامتر ورودی نیز بگیرند. برای مثال، کد زیر را در نظر بگیرید:
public class Spaceship {
public String name;
private int shieldStrength;
public Spaceship(String objectName) {
name = objectName;
shieldStrength = 200;
}
}
در سورس کد فوق، کانستراکتور این کلاس یک پارامتر ورودی از جنس String می گیرد که objectName نام دارد. داخل این کانستراکتور، مقدار name را برابر با objectName قرار داده ایم. حال به صورت زیر می بایست از روی کلاس Spaceship یک آبجکت جدید بسازیم:
Spaceship shahab = new Spaceship("Shahab 3");
در واقع، به محض ساخت یک آبجکت جدید از روی کلاس Spaceship، کانستراکتور فرا خوانده می شود اما از آن جا که این کانستراکتور دارای پارامتر ورودی است، در حین ساخت کلاس می بایست این پارامتر ورودی را به کلاس ()Spaceship پاس دهیم. در این مثال، یک پارامتر ورودی همچون Shahab 3 را در نظر گرفته ایم. از این پس، شیء ساخته شده از روی کلاس Spaceship دارای نام شهاب 3 بوده و توان محافظتی آن برابر با 200 است. در یو ام ال هم کانستراکتورهایی که پارامتر ورودی می گیرند را به صورت زیر نمایش خواهیم داد:
اکنون که با مفهوم Constructor ها در برنامه نویسی شیء گرایی آشنا شدیم، نیاز است تا با نقطه ی مقابل آن ها یعنی Destructor (دیستراکتور به معنی مخرب) نیز آشنا شویم. وقتی که ما آبجکت یا آبجکت هایی از روی یک کلاس خاص ایجاد می کنیم، این آبجکت ها منجر به مصرف منابع سیستمی می شوند و این در حالی است که اگر سیستم ما با کمبود منابع -مثلا حافظه ی رم- رو به رو شود، در اجرای برنامه اختلال خواهد شد. در اینجا است که نقش دیستراکتورها دوچندان می شود. در واقع، ما با استفاده از دیستراکتورها خواهیم توانست آبجکت هایی که ایجاد کرده ایم اما دیگر به آن ها نیازی نداریم را اصطلاحا Destruct کرده یا «از بین ببریم»!