در این آموزش قصد داریم تا به منظور درک عملی کاربرد کانستراکتور، سناریویی تعریف کرده و آن را پیادهسازی نماییم. فرض میکنیم که میخواهیم برنامهای طراحی کنیم که در ابتدا نام کاربر سپس نام خودروی وی را میگیرد و در نهایت میزان سوخت مصرفیِ خودروی کاربر به ازای هر 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
را به منظور خواندن دیتای ورودیِ کاربر فراخوانی نمودیم.