JavaRush /جاوا بلاگ /Random-UR /جاوا میں تعمیر کنندگان

جاوا میں تعمیر کنندگان

گروپ میں شائع ہوا۔
ہیلو! آج ہم ایک انتہائی اہم موضوع پر نظر ڈالیں گے جس کا تعلق ہماری اشیاء سے ہے۔ یہاں، بغیر مبالغہ کے، ہم کہہ سکتے ہیں کہ آپ اس علم کو ہر روز حقیقی کام میں استعمال کریں گے! ہم کنسٹرکٹرز کے بارے میں بات کریں گے۔ ہو سکتا ہے آپ یہ اصطلاح پہلی بار سن رہے ہوں، لیکن درحقیقت آپ نے کنسٹرکٹرز کا استعمال کیا ہو گا، لیکن آپ نے خود اس پر توجہ نہیں دی :) ہم اسے بعد میں دیکھیں گے۔

جاوا میں کنسٹرکٹر کیا ہے اور اس کی ضرورت کیوں ہے؟

آئیے دو مثالیں دیکھتے ہیں۔
public class Car {

   String model;
   int maxSpeed;

   public static void main(String[] args) {

       Car bugatti = new Car();
       bugatti.model = "Bugatti Veyron";
       bugatti.maxSpeed = 407;

   }
}
ہم نے اپنی کار بنائی اور اس کا ماڈل اور زیادہ سے زیادہ رفتار مقرر کی۔ تاہم، ایک حقیقی پروجیکٹ میں، کار آبجیکٹ میں واضح طور پر 2 سے زیادہ فیلڈز ہوں گے۔ اور، مثال کے طور پر، 16 فیلڈز!
public class Car {

   String model;//model
   int maxSpeed;//max speed
   int wheels;// disk width
   double engineVolume;//engine capacity
   String color;//color
   int yearOfIssue;//year of issue
   String ownerFirstName;//Owner's name
   String ownerLastName;//owner's last name
   long price;//price
   boolean isNew;//new or not
   int placesInTheSalon;//number of seats in the cabin
   String salonMaterial;// interior material
   boolean insurance;//is it insured
   String manufacturerCountry;//manufacturer country
   int trunkVolume;// trunk volume
   int accelerationTo100km;//acceleration to 100 km/h in seconds


   public static void main(String[] args) {
       Car bugatti = new Car();

       bugatti.color = "blue";
       bugatti.accelerationTo100km = 3;
       bugatti.engineVolume = 6.3;
       bugatti.manufacturerCountry = "Italy";
       bugatti.ownerFirstName = "Amigo";
       bugatti.yearOfIssue = 2016;
       bugatti.insurance = true;
       bugatti.price = 2000000;
       bugatti.isNew = false;
       bugatti.placesInTheSalon = 2;
       bugatti.maxSpeed = 407;
       bugatti.model = "Bugatti Veyron";

   }

}
ہم نے ایک نیا کار آبجیکٹ بنایا ہے ۔ ایک مسئلہ: ہمارے پاس 16 فیلڈز ہیں، لیکن ہم نے صرف 12 کو شروع کیا ! ان کو تلاش کرنے کے لیے ابھی کوڈ استعمال کرنے کی کوشش کریں جنہیں ہم بھول گئے ہیں! اتنا آسان نہیں، ٹھیک ہے؟ ایسی صورت حال میں، پروگرامر آسانی سے غلطی کر سکتا ہے اور کسی فیلڈ کی شروعات کو چھوڑ سکتا ہے۔ نتیجے کے طور پر، پروگرام کا رویہ غلط ہو جائے گا:
public class Car {

   String model;//model
   int maxSpeed;//max speed
   int wheels;// disk width
   double engineVolume;//engine capacity
   String color;//color
   int yearOfIssue;//year of issue
   String ownerFirstName;//Owner's name
   String ownerLastName;//owner's last name
   long price;//price
   boolean isNew;//new or not
   int placesInTheSalon;//number of seats in the cabin
   String salonMaterial;// interior material
   boolean insurance;//is it insured
   String manufacturerCountry;//manufacturer country
   int trunkVolume;// trunk volume
   int accelerationTo100km;//acceleration to 100 km/h in seconds


   public static void main(String[] args) {
       Car bugatti = new Car();

       bugatti.color = "blue";
       bugatti.accelerationTo100km = 3;
       bugatti.engineVolume = 6.3;
       bugatti.manufacturerCountry = "Italy";
       bugatti.ownerFirstName = "Amigo";
       bugatti.yearOfIssue = 2016;
       bugatti.insurance = true;
       bugatti.price = 2000000;
       bugatti.isNew = false;
       bugatti.placesInTheSalon = 2;
       bugatti.maxSpeed = 407;
       bugatti.model = "Bugatti Veyron";

       System.out.println("Model Bugatti Veyron. Engine size - " + bugatti.engineVolume + ", trunk - " + bugatti.trunkVolume + ", salon is made of" + bugatti.salonMaterial +
       ", disc width - " + bugatti.wheels + ". Was acquired in 2018 by Mr. " + bugatti.ownerLastName);

   }

}
کنسول آؤٹ پٹ:
بگٹی ویرون ماڈل۔ انجن کی نقل مکانی - 6.3، ٹرنک - 0، نل سے بنا اندرونی حصہ، رم کی چوڑائی - 0. مسٹر نل نے 2018 میں خریدا تھا۔
آپ کا خریدار، جس نے کار کے لیے $2 ملین ادا کیے، ظاہر ہے "مسٹر نال" کہلانا پسند نہیں کرے گا! لیکن سنجیدگی سے، آخر میں، ہمارا پروگرام ایک غلط طریقے سے بنائی گئی چیز کے ساتھ ختم ہوا - ایک کار جس کی رم چوڑائی 0 ہے (یعنی کوئی رم نہیں ہے)، ایک گم شدہ ٹرنک، نامعلوم مواد سے بنا ہوا اندرونی حصہ، اور یہاں تک کہ کسی نامعلوم شخص سے تعلق رکھتا ہے۔ . کوئی صرف سوچ سکتا ہے کہ پروگرام کے چلتے ہوئے ایسی غلطی کیسے ہو سکتی ہے! ہمیں کسی نہ کسی طرح ایسے حالات سے بچنا چاہیے۔ ہمیں اپنے پروگرام کی ایک حد کی ضرورت ہے: نئی گاڑی کی آبجیکٹ بناتے وقت، مثال کے طور پر، اس کے لیے ہمیشہ ماڈل اور زیادہ سے زیادہ رفتار کی وضاحت ہونی چاہیے۔ بصورت دیگر، آبجیکٹ بنانے کی اجازت نہ دیں۔ کنسٹرکٹر کے افعال آسانی سے اس کام سے نمٹتے ہیں۔ ان کا نام ایک وجہ سے ملا۔ کنسٹرکٹر کلاس کا ایک قسم کا "کنکال" بناتا ہے، جس سے کلاس کے ہر نئے آبجیکٹ کو مساوی ہونا چاہیے۔ سہولت کے لیے، آئیے دو فیلڈز کے ساتھ کار کلاس کے ایک آسان ورژن پر واپس آتے ہیں۔ ہماری ضروریات کو دیکھتے ہوئے، کار کلاس کا کنسٹرکٹر اس طرح نظر آئے گا:
public Car(String model, int maxSpeed) {
   this.model = model;
   this.maxSpeed = maxSpeed;
}
اور اب ایک آبجیکٹ بنانا اس طرح لگتا ہے:
public static void main(String[] args) {
   Car bugatti = new Car("Bugatti Veyron", 407);
}
توجہ فرمایےکنسٹرکٹر کیسے بنایا جاتا ہے۔ یہ ایک باقاعدہ طریقہ کی طرح ہے، لیکن اس میں واپسی کی قسم نہیں ہے۔ اس صورت میں، کلاس کا نام کنسٹرکٹر میں، بڑے حرف کے ساتھ بھی ظاہر ہوتا ہے۔ ہمارے معاملے میں - کار ۔ اس کے علاوہ، کنسٹرکٹر آپ کو نیا مطلوبہ لفظ استعمال کرتا ہے this ۔ انگریزی میں "this" کا مطلب ہے "یہ، یہ"۔ یہ لفظ کسی خاص چیز کی طرف اشارہ کرتا ہے۔ کنسٹرکٹر میں کوڈ:
public Car(String model, int maxSpeed) {
   this.model = model;
   this.maxSpeed = maxSpeed;
}
تقریباً لفظی ترجمہ کیا جا سکتا ہے: " اس مشین کے لیے ماڈل (جو اب ہم بنا رہے ہیں) = ماڈل آرگومنٹ ، جو کنسٹرکٹر میں بیان کیا گیا ہے۔ اس مشین کے لیے maxSpeed ​​(جسے ہم بنا رہے ہیں) = maxSpeed ​​دلیل ، جو کنسٹرکٹر میں بیان کیا گیا ہے۔" یہ ہوا ہے:
public class Car {

   String model;
   int maxSpeed;

   public Car(String model, int maxSpeed) {
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   public static void main(String[] args) {
       Car bugatti = new Car("Bugatti Veyron", 407);
       System.out.println(bugatti.model);
       System.out.println(bugatti.maxSpeed);
   }

}
کنسول آؤٹ پٹ:
بگٹی ویرون 407
کنسٹرکٹر نے مطلوبہ اقدار کو کامیابی کے ساتھ تفویض کیا۔ آپ نے دیکھا ہوگا کہ کنسٹرکٹر ایک باقاعدہ طریقہ سے بہت ملتا جلتا ہے! یہ اس طرح ہے: کنسٹرکٹر ایک طریقہ ہے، صرف تھوڑا سا مخصوص :) بالکل اسی طرح جیسے ایک طریقہ میں، ہم نے اپنے کنسٹرکٹر کو پیرامیٹرز بھیجے ہیں۔ اور کسی طریقہ کو کال کرنے کی طرح، کنسٹرکٹر کو کال کرنا کام نہیں کرے گا اگر آپ ان کی وضاحت نہیں کرتے ہیں:
public class Car {

   String model;
   int maxSpeed;

   public Car(String model, int maxSpeed) {
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   public static void main(String[] args) {
       Car bugatti = new Car(); //error!
   }

}
آپ نے دیکھا، ڈیزائنر نے وہی کیا جو ہم حاصل کرنے کی کوشش کر رہے تھے۔ اب آپ بغیر رفتار کے یا ماڈل کے بغیر گاڑی نہیں بنا سکتے! تعمیر کنندگان اور طریقوں کے مابین مماثلتیں وہیں ختم نہیں ہوتی ہیں۔ بالکل طریقوں کی طرح، کنسٹرکٹرز کو اوورلوڈ کیا جا سکتا ہے۔ تصور کریں کہ آپ کے گھر میں 2 بلیاں ہیں۔ آپ نے ان میں سے ایک کو بلی کے بچے کے طور پر لیا، اور دوسرے کو آپ بالغ ہونے پر گلی سے گھر لے آئے اور آپ کو بالکل نہیں معلوم کہ اس کی عمر کتنی ہے۔ اس کا مطلب یہ ہے کہ ہمارے پروگرام کو دو قسم کی بلیاں بنانے کے قابل ہونا چاہیے - پہلی بلی کے لیے نام اور عمر کے ساتھ، اور صرف ایک نام کے ساتھ - دوسری بلی کے لیے۔ ایسا کرنے کے لیے، ہم کنسٹرکٹر کو اوورلوڈ کریں گے:
public class Cat {

   String name;
   int age;

   //for the first cat
   public Cat(String name, int age) {
       this.name = name;
       this.age = age;
   }

   //for the second cat
   public Cat(String name) {
       this.name = name;
   }

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5);
       Cat streetCatNamedBob = new Cat("Bob");
   }

}
"نام" اور "عمر" کے پیرامیٹرز کے ساتھ اصل کنسٹرکٹر میں ہم نے ایک اور شامل کیا، صرف ایک نام کے ساتھ۔ ہم نے پچھلے اسباق میں اسی طرح طریقوں کو اوورلوڈ کیا۔ اب ہم بلیوں کے دونوں ورژن کامیابی کے ساتھ بنا سکتے ہیں :) کنسٹرکٹرز کی ضرورت کیوں ہے؟  - 2کیا آپ کو یاد ہے کہ لیکچر کے آغاز میں ہم نے کہا تھا کہ آپ نے کنسٹرکٹرز کو پہلے ہی استعمال کیا تھا، لیکن آپ نے ابھی اس پر توجہ نہیں دی؟ یہ حقیقت ہے. حقیقت یہ ہے کہ جاوا میں ہر کلاس کا ایک نام نہاد ڈیفالٹ کنسٹرکٹر ہوتا ہے۔ اس کے پاس کوئی دلائل نہیں ہیں، لیکن جب بھی کسی بھی طبقے کی کوئی چیز بنائی جاتی ہے تو یہ فائر ہوجاتا ہے۔
public class Cat {

   public static void main(String[] args) {

       Cat barsik = new Cat(); //this is where the default constructor worked
   }
}
پہلی نظر میں یہ قابل توجہ نہیں ہے۔ ٹھیک ہے، ہم نے ایک چیز بنائی اور اسے بنایا، ڈیزائنر کا کام کہاں ہے؟ اسے دیکھنے کے لیے، آئیے اپنے ہاتھوں سے کیٹ کلاس کے لیے ایک خالی کنسٹرکٹر لکھیں ، اور اس کے اندر ہم کنسول پر کچھ فقرے پرنٹ کریں گے۔ اگر یہ ظاہر ہوتا ہے، تو کنسٹرکٹر نے کام کیا ہے۔
public class Cat {

   public Cat() {
       System.out.println("Created a cat!");
   }

   public static void main(String[] args) {

       Cat barsik = new Cat(); //this is where the default constructor worked
   }
}
کنسول آؤٹ پٹ:
انہوں نے ایک بلی بنائی!
یہاں تصدیق ہے! ڈیفالٹ کنسٹرکٹر ہمیشہ آپ کی کلاسوں میں پوشیدہ طور پر موجود ہوتا ہے۔ لیکن آپ کو اس کی ایک اور خصوصیت جاننے کی ضرورت ہے۔ جب آپ دلائل کے ساتھ کچھ کنسٹرکٹر بناتے ہیں تو ڈیفالٹ کنسٹرکٹر کلاس سے غائب ہوجاتا ہے۔ اس کا ثبوت، حقیقت میں، ہم پہلے ہی اوپر دیکھ چکے ہیں. یہاں اس کوڈ میں:
public class Cat {

   String name;
   int age;

   public Cat(String name, int age) {
       this.name = name;
       this.age = age;
   }

   public static void main(String[] args) {

       Cat barsik = new Cat(); //error!
   }
}
ہم نام اور عمر کے بغیر بلی نہیں بنا سکتے تھے کیونکہ ہم نے Cat : string + number کے لیے کنسٹرکٹر کی تعریف کی تھی۔ پہلے سے طے شدہ کنسٹرکٹر اس کے فوراً بعد کلاس سے غائب ہو گیا۔ لہذا، یاد رکھنا یقینی بنائیں: اگر آپ کو اپنی کلاس میں متعدد کنسٹرکٹرز کی ضرورت ہے، بشمول ایک خالی، آپ کو اسے الگ سے بنانا ہوگا۔ مثال کے طور پر، ہم ویٹرنری کلینک کے لیے ایک پروگرام بنا رہے ہیں۔ ہمارا کلینک اچھے کام کرنا اور بے گھر بلیوں کی مدد کرنا چاہتا ہے، جن کے بارے میں ہمیں ان کا نام یا عمر نہیں معلوم۔ پھر ہمارا کوڈ اس طرح نظر آنا چاہئے:
public class Cat {

   String name;
   int age;

   //for domestic cats
   public Cat(String name, int age) {
       this.name = name;
       this.age = age;
   }

   //for street cats
   public Cat() {
   }

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5);
       Cat streetCat = new Cat();
   }
}
اب جب کہ ہم نے واضح طور پر ایک ڈیفالٹ کنسٹرکٹر لکھا ہے، ہم دونوں قسم کی کیٹس بنا سکتے ہیں :) کنسٹرکٹر کے لیے (کسی بھی طریقہ کے لیے)، دلائل کی ترتیب بہت اہم ہے۔ آئیے اپنے کنسٹرکٹر میں نام اور عمر کے دلائل کو تبدیل کریں۔
public class Cat {

   String name;
   int age;

   public Cat(int age, String name) {
       this.name = name;
       this.age = age;
   }

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 10); //error!
   }
}
غلطی! کنسٹرکٹر واضح طور پر کہتا ہے کہ جب ایک کیٹ آبجیکٹ بنایا جاتا ہے، تو اسے اس ترتیب میں ایک نمبر اور ایک تار پاس کرنا چاہیے۔ اس لیے ہمارا کوڈ کام نہیں کرتا۔ اس بات کو یقینی بنائیں اور اپنی کلاسز بناتے وقت اسے ذہن میں رکھیں:
public Cat(String name, int age) {
   this.name = name;
   this.age = age;
}

public Cat(int age, String name) {
   this.age = age;
   this.name = name;
}
یہ دو بالکل مختلف ڈیزائنرز ہیں! اگر ہم اس سوال کا جواب دیتے ہیں کہ "ہمیں کنسٹرکٹر کی ضرورت کیوں ہے؟" ایک جملے میں، ہم کہہ سکتے ہیں: تاکہ اشیاء ہمیشہ درست حالت میں ہوں۔ جب آپ کنسٹرکٹرز استعمال کرتے ہیں، تو آپ کے تمام متغیرات کو صحیح طریقے سے شروع کیا جائے گا، اور پروگرام میں اسپیڈ 0 یا دیگر "غلط" اشیاء والی کاریں نہیں ہوں گی۔ ان کا استعمال سب سے پہلے خود پروگرامر کے لیے بہت فائدہ مند ہے۔ اگر آپ فیلڈز کو خود شروع کرتے ہیں، تو کسی چیز کے گم ہونے اور غلطی کرنے کا بہت زیادہ خطرہ ہوتا ہے۔ لیکن یہ ایک کنسٹرکٹر کے ساتھ نہیں ہوگا: اگر آپ نے تمام مطلوبہ دلائل اس کے پاس نہیں کیے یا ان کی اقسام کو ملایا تو، مرتب کرنے والا فوری طور پر ایک غلطی پھینک دے گا۔ یہ الگ سے قابل ذکر ہے کہ آپ کو اپنے پروگرام کی منطق کو کنسٹرکٹر کے اندر نہیں ڈالنا چاہئے۔ ایسا کرنے کے لیے، آپ کے پاس ایسے طریقے ہیں جن میں آپ اپنی ضرورت کی تمام فعالیت کو بیان کر سکتے ہیں۔ آئیے دیکھتے ہیں کہ کنسٹرکٹر منطق کیوں برا خیال ہے:
public class CarFactory {

   String name;
   int age;
   int carsCount;

   public CarFactory(String name, int age, int carsCount) {
   this.name = name;
   this.age = age;
   this.carsCount = carsCount;

   System.out.println("Our car factory is called" + this.name);
   System.out.println("She was founded" + this.age + " years ago" );
   System.out.println("During this time it was produced" + this.carsCount +  "cars");
   System.out.println("On average she produces" + (this.carsCount/this.age) + "cars per year");
}

   public static void main(String[] args) {

       CarFactory ford = new CarFactory("Ford", 115 , 50000000);
   }
}
ہمارے پاس کارفیکٹری کلاس ہے جو کاریں بنانے والی فیکٹری کی وضاحت کرتی ہے۔ کنسٹرکٹر کے اندر، ہم تمام فیلڈز کو شروع کرتے ہیں اور منطق کو یہاں رکھتے ہیں: ہم فیکٹری کے بارے میں کچھ معلومات کنسول پر ظاہر کرتے ہیں۔ ایسا لگتا ہے کہ اس کے ساتھ کچھ بھی غلط نہیں ہے، پروگرام نے بالکل کام کیا. کنسول آؤٹ پٹ:
ہماری کار فیکٹری کا نام فورڈ ہے۔ اس کی بنیاد 115 سال پہلے رکھی گئی تھی۔ اس دوران اس نے 50,000,000 کاریں تیار کیں۔ اوسطاً یہ سالانہ 434,782 کاریں تیار کرتی ہے۔
لیکن درحقیقت ہم نے ٹائم بم نصب کر رکھا ہے۔ اور اس طرح کا کوڈ بہت آسانی سے غلطیوں کا باعث بن سکتا ہے۔ آئیے تصور کریں کہ اب ہم فورڈ کے بارے میں نہیں بلکہ نئی فیکٹری "امیگو موٹرز" کے بارے میں بات کر رہے ہیں، جو ایک سال سے بھی کم عرصے سے موجود ہے اور اس نے 1000 کاریں تیار کی ہیں:
public class CarFactory {

   String name;
   int age;
   int carsCount;

   public CarFactory(String name, int age, int carsCount) {
   this.name = name;
   this.age = age;
   this.carsCount = carsCount;

   System.out.println("Our car factory is called" + this.name);
   System.out.println("She was founded" + this.age + " years ago" );
   System.out.println("During this time it was produced" + this.carsCount +  "cars");
   System.out.println("On average she produces" + (this.carsCount/this.age) + "cars per year");
}


   public static void main(String[] args) {

       CarFactory ford = new CarFactory("Amigo Motors", 0 , 1000);
   }
}
کنسول آؤٹ پٹ:
ہماری کار فیکٹری کو "main" java.lang.ArithmeticException: / by zero میں Amigo Motors Exception کہا جاتا ہے اس کی بنیاد 0 سال پہلے رکھی گئی تھی اس دوران، اس نے CarFactory میں 1000 کاریں تیار کیں۔<init>(CarFactory.java:15) CarFactory.main(CarFactory.java:23) ایگزٹ کوڈ 1 کے ساتھ عمل مکمل ہوا</init>
ہم پہنچ چکے ہیں! پروگرام کچھ عجیب خرابی کے ساتھ ختم ہوا۔ کیا آپ اندازہ لگانے کی کوشش کریں گے کہ اس کی وجہ کیا ہے؟ وجہ وہ منطق ہے جو ہم نے کنسٹرکٹر میں رکھی ہے۔ خاص طور پر، اس لائن میں:
System.out.println("On average she produces" + (this.carsCount/this.age) + "cars per year");
یہاں ہم حساب لگاتے ہیں اور فیکٹری کی عمر کے حساب سے تیار کی گئی کاروں کی تعداد کو تقسیم کرتے ہیں۔ اور چونکہ ہماری فیکٹری نئی ہے (یعنی یہ 0 سال پرانی ہے)، نتیجہ 0 سے تقسیم ہے، جو کہ ریاضی میں ممنوع ہے۔ نتیجے کے طور پر، پروگرام ایک غلطی کے ساتھ ختم ہو جاتا ہے. ہمیں کیا کرنا چاہیے تھا؟ تمام منطق کو ایک الگ طریقہ میں منتقل کریں اور اسے کال کریں، مثال کے طور پر printFactoryInfo() ۔ آپ اسے CarFactory آبجیکٹ کو بطور پیرامیٹر پاس کر سکتے ہیں ۔ آپ تمام منطقیں بھی وہاں رکھ سکتے ہیں، اور ساتھ ہی - ممکنہ غلطیوں پر کارروائی کرنا، جیسا کہ ہماری طرح صفر سال کے ساتھ۔ ہر ایک کو اپنا۔ کسی چیز کی حالت کو صحیح طریقے سے ترتیب دینے کے لیے کنسٹرکٹرز کی ضرورت ہوتی ہے۔ کاروباری منطق کے لیے ہمارے پاس طریقے ہیں۔ آپ کو ایک کو دوسرے کے ساتھ نہیں ملانا چاہئے۔
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION