در این آموزش قصد داریم تا به منظور درک عملی کاربرد کانستراکتور، سناریویی تعریف کرده و آن را پیادهسازی نماییم. فرض میکنیم که میخواهیم برنامهای طراحی کنیم که در ابتدا نام کاربر سپس نام خودروی وی را میگیرد و در نهایت میزان سوخت مصرفیِ خودروی کاربر به ازای هر 100 کیلومتر را در خروجی نمایش دهیم. بنابراین در ابتدا یک پروژۀ جدید تحت عنوان MyCarAndI ایجاد میکنیم و کلاسی به نام FuelConsumption در آن میسازیم. در ادامه، به منظور نگهداری نام کاربر و همچنین نام خودروی وی، دو متغیر فیلد به صورت زیر تعریف میکنیم:
public class FuelConsumption {
String name;
String carName;
}
در کد فوق، دو آبجکت از نوع فیلد تحت عناوین name و carName از روی کلاس String ساختهایم که قرار است تا به ترتیب نام کاربر و نام خودروی وی را نگهداری کنند.
اکنون نیاز است تا یک کانستراکتور تعریف کنیم تا در صورت ساخت آبجکت از روی این کلاس، فراخوانی شده و متغیرهای فیلد تعریفشده در کلاس را مقداردهی اولیه نماید که برای این منظور کد فوق را به صورت زیر تکمیل میکنیم:
public class FuelConsumption {
String name;
String carName;
// Constructor
public FuelConsumption(String name, String carName) {
this.name = name;
this.carName = carName;
}
}
بخش کامنتشده از کد فوق مربوط به تعریف کانستراکتور کلاس میباشد که آن را با دو پارامتر ورودی تحت عناوین name و carName تعریف کردهایم (توجه داشته باشیم که پارامترهای ورودیِ کانستراکتور را با متغیرهای فیلد تعریفشده در کلاس اشتباه نگیریم.) و بدین ترتیب در صورت ساخت آبجکت از روی کلاس FuelConsumption میباید دو مقدار از جنس استرینگ را به عنوان ورودی به آبجکت تعریفشده پاس دهیم.
در ادامه، به دلیل همنام بودن پارامترهای ورودیِ کانستراکتور و متغیرهای فیلد، از کیورد this استفاده کردهایم تا کامپایلر در حین اجرای برنامه آنها را از یکدیگر تشخیص دهد. بنابراین داخل کانستراکتور با استفاده از کیورد this گفتهایم در صورت ساخت آبجکت از روی کلاس FuelConsumption مقادیر استرینگ ورودی برای آبجکت جدید به متغیرهای فیلد name و carName از همان کلاس منتسب شوند.
همچنین جهت چاپ مقادیر مربوط به نام کاربر و نام خودروی وی، نیاز به استفاده از مقادیر منتسب به متغیرهای مذکور در برخی نقاط برنامه داریم و از همین روی دو متد تعریف میکنیم تا مقادیر اختصاصیافته به آنها را در خروجی ریترن کنند و برای این منظور کد مربوط به کلاس FuelConsumption را به صورت زیر تکمیل مینماییم:
public class FuelConsumption {
String name;
String carName;
double fuelConsumption;
// Constructor
public FuelConsumption(String name, String carName) {
this.name = name;
this.carName = carName;
}
// Return Methods
public String returnName() {
return name;
}
public String returnCarName() {
return carName;
}
}
در کد فوق، دو متد به نامهای ()reurnName و ()returnCarName از جنس کلاس String تعریف کردهایم چرا که هر دو متد مذکور قرار است تا دیتایی از نوع دادۀ استرینگ را در خروجی ریترن کنند. در ادامه، دستورات داخلی متدها را تعریف کردهایم تا در صورت فراخوانی، به ترتیب مقادیر منتسب به متغیرهای name و carName را در خروجی ریترن نمایند.
در این مرحله کلاس جدیدی به نام ActionClass تعریف کرده و در حین ساخت کلاس نیز تیک گزینۀ public static void main را میزنیم تا کلاس مذکور به عنوان نقطۀ شروع برنامۀ در نظر گرفته شود. در ادامه، داخل کلاس ActionClass آبجکتی به نام objectOne از روی کلاس FuelConsumtion میسازیم که برای این منظور کد مربوط به کلاس ActionClass را به صورت زیر پیادهسازی مینماییم:
public class ActionClass {
public static void main(String[] args) {
FuelConsumption objectOne = new FuelConsumption(name, carName);
}
}
در واقع، برای ساخت آبجکت objectOne از روی کلاس FuelConsumption پس از نوشتن کیورد new و حرف «F» که از حرف اول کلاس مربوطه گرفته شده است، اکلیپس پیشنهاداتی به منظور تکمیل کد ارائه میدهد که در کد فوق دستور پیشنهادی اول را انتخاب کرده و میبینیم که آیدیای اکلیپس پارامترهای ورودی تعریفشده برای کانستراکتور کلاس را شناسایی کرده و کد مربوط به ساخت آبجکت جدید را با پاس دادن پارامترهای ورودی متناظرشان تکمیل مینماید و در ادامه میبینیم که واژههای مربوط به پارامترهای ورودی با نقطهچین مشخص شدهاند بدین معنی که مقادیر ورودیِ مربوط به آبجکت جدید به درستی تعریف نشدهاند چرا که این مقادیر میباید هر دو از جنس کلاس String بوده و مابین علائم " " به آبجکت جدید پاس داده شوند.
حال با آگاهی از این نکته، پارامترهای مربوط به آبجکت ساختهشده را داخل علامتهای " " قرار میدهیم و میبینیم که پس از سِیو کردن فایل مربوط به کلاس ActionClass ارور برنامه رفع میشود اما این دو نام به عنوان نام و نام خودروی کاربر اسامی گویایی نمیباشند و از همین روی در ادامه نامهای مناسبتری را به جای آنها مد نظر قرار میدهیم به طوری که در کد مربوط به کلاس ActionClass داریم:
public class ActionClass {
public static void main(String[] args) {
FuelConsumption objectOne = new FuelConsumption("Behzad", "206");
}
}
در کد فوق، آبجکتی جدید از روی کلاس FuelConsumption به نام objectOne ساخته و در ادامه مقادیر استرینگ «Behzad» و «206» را به ترتیب به پارامترهای ورودی name و carName منتسب میکنیم به طوری که به محض ساخت آبجکت از روی کلاس مذکور، کانستراکتور آن کلاس فراخوانی شده و مقادیر ورودیِ آبجکت جدید را به متغیرهای فیلدِ name و carName اختصاص میدهد.
حال اگر بخواهیم تا امکان دریافت دیتای ورودی از کاربر را برای برنامه فراهم کنیم، از کلاس Scanner استفاده کرده و در ابتدا به صورت زیر آبجکتی از روی آن در کلاس ActionClass میسازیم (برای آشنایی با کلاس Scanner به آموزش معرفی کلاس Scanner در زبان برنامهنویسی جاوا مراجعه نمایید):
import java.util.Scanner;
public class ActionClass {
public static void main(String[] args) {
Scanner keyboardInput = new Scanner(System.in);
String userName = keyboardInput.next();
String userCarName = keyboardInput.next();
FuelConsumption objectOne = new FuelConsumption(userName, userCarName);
keyboardInput.close();
}
}
در کد فوق، آبجکتی تحت عنوان keyboardInput از روی کلاس Scanner ساخته و با استفاده از دستور System.in امکان دسترسی سیستم به بخش ورودی آیدیای (بخش کنسول در اکلیپس) را فراهم میکنیم. در ادامه، متد ()next از کلاس Scanner را روی آبجکت جدید ساختهشده فراخوانی میکنیم و آن را به آبجکتی از روی کلاس String به نام userName منتسب میکنیم تا بدین ترتیب دیتای ورودی از طریق کیبورد خوانده شده و در خروجی ریترن شود و در ادامه دیتای ریترنشده از متد ()next در userName نگهداری خواهد شد (جهت آشنایی با متد ()next و سایر متدهای پرکاربرد کلاس Scanner به آموزش نحوۀ تعریف نوع ورودی کلاس Scanner در زبان برنامهنویسی جاوا مراجعه نمایید.)
در ادامه، به منظور دریافت نام خودروی کاربر از ورودی، مشابه نام کاربر عمل کرده و آبجکتی از روی کلاس String به نام userCarName ساخته و نتیجۀ حاصل از فراخوانی متد ()next روی آبجکت keyboardInput را بدان منتسب کرده سپس مقادیر دیتای ورودی به آبجکت ساختهشده از روی کلاس FuelConsomption را به ترتیب برابر با userName و userCarName قرار میدهیم که در چنین شرایطی به جای تعریف استرینگهای ورودی برای آبجکت جدید، آنها را از ورودی گرفته و به آبجکت مذکور پاس میدهیم.
اکنون نیاز داریم تا با کاربر خود تعامل داشته باشیم و محتوایی را در ابتدا در کنسول چاپ کنیم تا به او اطلاع دهیم که به ترتیب نام و نام خودروی خود را وارد برنامه نماید که برای این منظور کد مربوط به کلاس ActionClass را به صورت زیر تکمیل میکنیم:
import java.util.Scanner;
public class ActionClass {
public static void main(String[] args) {
Scanner keyboardInput = new Scanner(System.in);
System.out.print("Please enter your name: ");
String userName = keyboardInput.next();
System.out.print("Please enter your Car type: ");
String userCarName = keyboardInput.next();
FuelConsumption objectOne = new FuelConsumption(userName, userCarName);
keyboardInput.close();
}
}
بنابراین در کد فوق با استفاده از متد ()print ابتدا استرینگ «:Please enter your name» را در کنسول چاپ میکنیم و برنامه در همان سطر منتظر دریافت ورودی از کاربر میماند؛ سپس نام کاربر را گرفته و آن را به userName اختصاص میدهد. به همین ترتیب استرینگ «:Please enter your car type» چاپ شده و برنامه در همان سطر منتظر دریافت نام خوردروی کاربر مانده سپس آن را به userCarName منتسب میکند و در ادامه هر یک از مقادیر منتسب به آبجکتهای userName و userCarName به عنوان ورودی به آبجکت جدید objectOne ساختهشده از روی کلاس FuelConsomption پاس داده میشوند به طوری که با اجرای برنامۀ فوق در خروجی خواهیم داشت:
Please enter your name: Behzad
Please enter your Car type: Hummerدر اجرای فوق ابتدا نام خود را وارد کرده سپس نام یک خودرو (در این مثال هامر) را وارد برنامه کردهایم که به محض انجام این کار، دو استرینگ ورودیِ مربوط به نام و نام خودرو به عنوان پارامترهای ورودیِ کانستراکتور و بالتبع مقادیر متغیرهای فیلدِ کلاس FuelConsumption مد نظر قرار داده میشوند.
تا به این مرحله توانستهایم با موفقیت مقادیر پارامترهای ورودی برنامه را مشخص کنیم؛ در ادامه نیاز است تا اطلاعات مربوط به مسافت طیشده و همچنین مقدار بنزین موجود در باک خودروی کاربر را از ورودی بگیریم و برای این منظور کد کلاس فوق را به صورت زیر تکمیل میکنیم:
import java.util.Scanner;
public class ActionClass {
public static void main(String[] args) {
Scanner keyboardInput = new Scanner(System.in);
System.out.print("Please enter your name: ");
String userName = keyboardInput.next();
System.out.print("Please enter your Car type: ");
String userCarName = keyboardInput.next();
FuelConsumption objectOne = new FuelConsumption(userName, userCarName);
// Code related to distance and fuel amount
System.out.print("How many kilometers did you go with your car: ");
double distance = keyboardInput.nextDouble();
System.out.print("How much petrol did your car use? ");
double petrolUsed = keyboardInput.nextDouble();
keyboardInput.close();
}
}
در ادامۀ دستورات مربوط به دریافت نام و نام خودروی کاربر، قصد داریم تا ابتدا استرینگ «?How many kilometers did you go with your car» را در کنسول چاپ کرده و از کاربر بخواهیم تا مسافت پیمودهشده با خودرو را وارد برنامه کند که برای این منظور پس از چاپ استرینگ مربوطه، متد ()nextDouble را روی آبجکت ساختهشده از روی کلاس Scanner فراخوانی مینماییم و نتیجۀ حاصل از این فراخوانی را به متغیری تحت عنوان distance که با استفاده از دیتا تایپ double تعریف شده است منتسب مینماییم (توجه داشته باشیم که اگر کاربر یک عدد صحیح مانند 90 را وارد برنامه کند، مقدار ورودی به صورت خودکار به یک عدد اعشاری تبدیل شده و متد ()nextDouble آن را به صورت 90.0 در خروجی ریترن میکند.)
به همین منوال، ابتدا استرینگ «?How much petrol did your car use» را در پنجرۀ کنسول نمایش داده سپس متد ()nextDouble را روی آبجکت keyboardInput فراخوانی نمودهایم و در ادامه آن را به متغیر تعریفشده با دیتا تایپ double تحت عنوان petrolUsed منتسب میکنیم که در نتیجه دیتای مربوط به مقدار بنزین موجود در باک خودروی کاربر در متغیر petrolUsed نگهداری میشود. اکنون مجدداً برنامه را اجرا کرده و در خروجی خواهیم داشت:
Please enter your name: Behzad
Please enter your Car type: 206
How many kilometers did you go with your car: 145
How much petrol did your car use? 45همانطور که ملاحظه میکنیم، برنامه به درستی کار کرده و اطلاعات کاربر را از ورودی دریافت میکند. در این مرحله به منظور محاسبۀ سوخت مصرفی خودرو، فرمولی ریاضیاتی را به صورت زیر مد نظر قرار میدهیم:
8x=115100
در واقع، اگر فرض کنیم که با 8 لیتر بنزین میتوانیم مسافتی معادل 115 کیلومتر را طی کنیم، در ادامه قصد داریم تا ببینیم که طی مسافتی معادل 100 کیلومتر با چه مقدار بنزینی امکانپذیر میباشد و برای این کار عدد 100 را در عدد 8 ضرب کرده و مقدار حاصل را بر عدد 115 تقسیم میکنیم که با این کار مقدار مجهول x را به دست میآوریم.
بنابراین به منظور محاسبۀ میزان مصرف سوخت، نیاز است تا عدد 100 را در مقدار منتسب به متغیر petrolUsed ضرب کرده و حاصلضرب این دو عدد را بر مقدار اختصاصیافته به متغیر distance تقسیم کنیم و برای این کار کد فوق را به صورت زیر تکمیل میکنیم:
import java.util.Scanner;
public class ActionClass {
public static void main(String[] args) {
Scanner keyboardInput = new Scanner(System.in);
System.out.print("Please enter your name: ");
String userName = keyboardInput.next();
System.out.print("Please enter your Car type: ");
String userCarName = keyboardInput.next();
FuelConsumption objectOne = new FuelConsumption(userName, userCarName);
// Code related to distance and fuel amount
System.out.print("How many kilometers did you go with your car: ");
double distance = keyboardInput.nextDouble();
System.out.print("How much petrol did your car use? ");
double petrolUsed = keyboardInput.nextDouble();
double result = 100 * petrolUsed / distance;
System.out.println(result);
keyboardInput.close();
}
}
همانطور که ملاحظه میکنیم، در دو سطر آخر کد با استفاده از دیتا تایپ duoble متغیری به نام result تعریف کرده و فرمول محاسبهٔ مصرف در هر 100 کیلومتر را پیادهسازی کرده و حاصل را بدان منتسب کردهایم و در سطر بعد نیز مقدار اختصاصیافته به این متغیر را با استفاده از متد ()println در کنسول چاپ میکنیم. حال مجدداً برنامۀ فوق را اجرا میکنیم و در خروجی خواهیم داشت:
Please enter your name: Behzad
Please enter your Car type: 206
How many kilometers did you go with your car: 145
How much petrol did your car use? 12
8.275862068965518همانطور که در خروجی میبینیم، پس از طی مسافتی معادل 145 کیلومتر و مصرف 12 لیتر بنزین برنامه مقدار سوخت مصرفی را معادل 8/2758 در هر 100 کیلومتر محاسبه کرده است که یک عدد بسیار دقیق میباشد و به منظور رُند کردن آن نیز میتوانیم متد موجود ()round از کلاس Math را فراخوانی نموده و مقدار منتسب به متغیر result را به عنوان آرگومان ورودی به آن پاس دهیم که برای این منظور به روش زیر عمل کرده و آن را به کد کلاس ActionClass اضافه میکنیم:
double result = 100 * petrolUsed / distance;
System.out.println(Math.round(result));
بنابراین با فراخوانی متد ()round از کلاس Math و پاس دادن مقدار متغیر result به آن، عدد 8/2758 رُند شده و در خروجی ریترن میشود که مقدار خروجی نیز توسط متد ()println در کنسول چاپ میگردد. اکنون برنامه را با همان اطلاعات ورودی در اجرای فوق مجدداً اجرا میکنیم و در خروجی خواهیم داشت:
Please enter your name: Behzad
Please enter your Car type: 206
How many kilometers did you go with your car: 145
How much petrol did your car use? 12
8همانطور که میبینیم، خروجی برنامه کاملاً رُند شده است به طوری که پس از طی 145 کیلومتر مسافت و مصرف 12 لیتر بنزین، در هر 100 کیلومتر فقط 8 لیتر بنزین مصرف کردهایم. اکنون برای تکمیل برنامه میتوانیم به جای نمایش دادن مقدار منتسب به متغیر result دستوری بنویسیم تا مقدار منتسب به این متغیر با استرینگی مانند «.Dear Behzad, your 206 car used 8 liters petrol per 100 kilometers» کانکت شده و در کنسول چاپ شود که برای این منظور به سادگی میتوانیم هر یک از مقادیر استرینگ مربوط به نام، نام خودرو و میزان سوخت مصرفی را با استفاده از متد ()println با استرینگهای مربوطه کانکت کرده و در کنسول چاپ نماییم و برای این منظور کد مربوط به کلاس ActionClass را به صورت زیر تکمیل میکنیم:
import java.util.Scanner;
public class ActionClass {
public static void main(String[] args) {
Scanner keyboardInput = new Scanner(System.in);
System.out.print("Please enter your name: ");
String userName = keyboardInput.next();
System.out.print("Please enter your Car type: ");
String userCarName = keyboardInput.next();
FuelConsumption objectOne = new FuelConsumption(userName, userCarName);
// Code related to distance and fuel amount
System.out.print("How many kilometers did you go with your car: ");
double distance = keyboardInput.nextDouble();
System.out.print("How much petrol did your car use? ");
double petrolUsed = keyboardInput.nextDouble();
double result = 100 * petrolUsed / distance;
System.out.println("Dear " + objectOne.returnName() + ", your " + objectOne.returnCarName() + " car consumes " + Math.round(result) + " liters petrol in 100 kilometers.");
keyboardInput.close();
}
}
بنابراین به منظور چاپ استرینگ مد نظر به همراه مقادیر مربوط به نام، نام خودرو و همچنین مقدار سوخت مصرفی خودروی کاربر دستور سطر شانزدهم را به کد فوق افزودهایم و همانطور که میبینیم استرینگهای مورد نظر مابین علائم " " قرار گرفته و با استفاده از عملگر + به ترتیب با مقدار حاصل از فراخوانی متد ()returnName از کلاس FuelConsumption روی آبجکت ساختهشده از روی این کلاس، مقدار حاصل از فراخوانی متد ()returnCarName روی آبجکت مذکور و مقدار سوخت مصرفیِ رُندشده در نتیجۀ فراخوانی متد ()round با آرگومان ورودی منتسب به متغیر result کانکت کرده و در خروجی ریترن میکند. بنابراین استرینگهای مورد نظر به همراه مقدار ریترنشده به عنوان نام کاربر، نام خودروی کاربر و مقدار سوخت مصرفی در هر 100 کیلومتر در کنسول چاپ میشوند:
Please enter your name: Behzad
Please enter your Car type: 206
How many kilometers did you go with your car: 180
How much petrol did your car use? 13
Dear Behzad, your 206 car consumes 7 liters petrol in 100 kilometers.همانطور که ملاحظه میکنیم، برنامه به درستی کار کرده و آخرین دستور اضافهشده به کد کلاس ActionClass مقادیر ریترنشده از متدهای ()returnCarName و ()returnName و همچنین مقدار منتسب به متغیر result را با استرینگهای مربوطه کانکت کرده و در کنسول نمایش میدهد.
به طور کلی، در این آموزش کانستراکتوری برای کلاس FuelConsumption پیادهسازی کردیم و دیدیم که چگونه میتوان مقادیر مورد نظر خود را به آبجکت جدید ساختهشده از روی کلاس داد تا کانستراکتور در حین فراخوانی آنها را متغیرهای فیلد تعریفشده اختصاص دهد. به علاوه، به منظور دریافت دیتای ورودی به صورت دینامیک، از کلاس Scanner استفاده کرده و متدهای تعبیهشده در آن از جمله ()next و ()nextDouble را به منظور خواندن دیتای ورودیِ کاربر فراخوانی نمودیم.
