CodeGym /جاوا بلاگ /Random-UR /جاوا کنسٹرکٹرز
John Squirrels
سطح
San Francisco

جاوا کنسٹرکٹرز

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

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

آئیے دو مثالوں پر غور کریں۔
public class Car {

   String model;
   int maxSpeed;

   public static void main(String[] args) {

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

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

   String model;// model
   int maxSpeed;// maximum speed
   int wheels;// wheel width
   double engineVolume;// engine volume
   String color;// color
   int productionYear;// production year
   String ownerFirstName;// first name of owner
   String ownerLastName;// last name of owner
   long price;// price
   boolean isNew;// flag indicating whether car is new
   int seatsInTheCar;// number of seats in the car
   String cabinMaterial;// interior material
   boolean insurance;// flag indicating whether car is insured
   String manufacturerCountry;// manufacturer country
   int trunkVolume;// size of the trunk
   int accelerationTo100km;// how long it takes to accelerate 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.productionYear = 2016;
       bugatti.insurance = true;
       bugatti.price = 2000000;
       bugatti.isNew = false;
       bugatti.seatsInTheCar = 2;
       bugatti.maxSpeed = 378;
       bugatti.model = "Bugatti Veyron";

   }

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

   String model;// model
   int maxSpeed;// maximum speed
   int wheels;// wheel width
   double engineVolume;// engine volume
   String color;// color
   int productionYear;// production year
   String ownerFirstName;// first name of owner
   String ownerLastName;// last name of owner
   long price;// price
   boolean isNew;// flag indicating whether car is new
   int seatsInTheCar;// number of seats in the car
   String cabinMaterial;// interior material
   boolean insurance;// flag indicating whether car is insured
   String manufacturerCountry;// manufacturer country
   int trunkVolume;// size of the trunk
   int accelerationTo100km;// how long it takes to accelerate 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.productionYear = 2016;
       bugatti.insurance = true;
       bugatti.price = 2000000;
       bugatti.isNew = false;
       bugatti.seatsInTheCar = 2;
       bugatti.maxSpeed = 378;
       bugatti.model = "Bugatti Veyron";

       System.out.println("Model: Bugatti Veyron. Engine volume: " + bugatti.engineVolume + ". Trunk volume: " + bugatti.trunkVolume + ". Cabin material: " + bugatti.cabinMaterial +
       ". Wheel width: " + bugatti.wheels + ". Purchased in 2018 by Mr. " + bugatti.ownerLastName);

   }

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

// And creating an object now looks like this:

public static void main(String[] args) {
   Car bugatti = new Car("Bugatti Veyron", 378);
}
نوٹ کریں کہ کنسٹرکٹر کا اعلان کیسے کیا جاتا ہے۔ یہ ایک باقاعدہ طریقہ کی طرح ہے، لیکن اس میں واپسی کی قسم نہیں ہے۔ مزید برآں، کنسٹرکٹر کلاس کا نام بتاتا ہے ( کار ) بڑے حروف سے شروع ہوتا ہے۔ مزید برآں، کنسٹرکٹر کو ایک کلیدی لفظ کے ساتھ استعمال کیا جاتا ہے جو آپ کے لیے نیا ہے: یہ ۔ کلیدی لفظ یہ کسی خاص چیز کی نشاندہی کرنے کے لیے ہے۔ کنسٹرکٹر میں کوڈ
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", 378);
       System.out.println(bugatti.model);
       System.out.println(bugatti.maxSpeed);
   }

}
کنسول آؤٹ پٹ: Bugatti Veyron 378 کنسٹرکٹر نے مطلوبہ اقدار کو صحیح طریقے سے تفویض کیا۔ آپ نے دیکھا ہوگا کہ کنسٹرکٹر ایک عام طریقہ سے بہت ملتا جلتا ہے! پس یہ ہے. کنسٹرکٹر واقعی ایک طریقہ ہے، لیکن مخصوص خصوصیات کے ساتھ :) بالکل اسی طرح جیسے طریقوں کے ساتھ، ہم نے اپنے کنسٹرکٹر کو دلائل بھیجے۔ اور کسی طریقہ کو کال کرنے کی طرح، کنسٹرکٹر کو کال کرنا اس وقت تک کام نہیں کرے گا جب تک کہ آپ ان کی وضاحت نہ کریں:
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 smudge = new Cat("Smudge", 5);
       Cat streetCatNamedBob = new Cat("Bob");
   }

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

   public static void main(String[] args) {

       Cat smudge = new Cat(); // The default constructor is invoked here
   }
}
پہلی نظر میں، یہ پوشیدہ ہے. ہم نے ایک چیز بنائی، تو کیا؟ کنسٹرکٹر یہاں کچھ کر رہا ہے کہاں؟ اسے دیکھنے کے لیے، کیٹ کلاس کے لیے واضح طور پر ایک خالی کنسٹرکٹر لکھیں ۔ ہم اس کے اندر کچھ جملہ دکھائیں گے۔ اگر جملہ ظاہر ہوتا ہے، تو کنسٹرکٹر کو پکارا گیا تھا۔
public class Cat {

   public Cat() {
       System.out.println("A cat has been created!");
   }

   public static void main(String[] args) {

       Cat smudge = new Cat(); // The default constructor is invoked here
   }
}
کنسول آؤٹ پٹ: ایک بلی بنائی گئی ہے! تصدیق ہے! ڈیفالٹ کنسٹرکٹر ہمیشہ آپ کی کلاسوں میں پوشیدہ طور پر موجود ہوتا ہے۔ لیکن آپ کو اس کے بارے میں ایک اور چیز جاننے کی ضرورت ہے۔ ایک بار جب آپ دلائل کے ساتھ کنسٹرکٹر بناتے ہیں تو پہلے سے طے شدہ کنسٹرکٹر کو کلاس سے ختم کردیا جاتا ہے۔ درحقیقت، ہم پہلے ہی اوپر اس کا ثبوت دیکھ چکے ہیں۔ یہ اس کوڈ میں تھا:
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 smudge = new Cat(); //Error!
   }
}
ہم نام اور عمر کے بغیر ایک بلی نہیں بنا سکتے تھے ، کیونکہ ہم نے سٹرنگ اور انٹ پیرامیٹرز کے ساتھ کیٹ کنسٹرکٹر کا اعلان کیا ہے۔ اس کی وجہ سے ڈیفالٹ کنسٹرکٹر کلاس سے فوری طور پر غائب ہو گیا۔ لہذا یہ یاد رکھنا یقینی بنائیں کہ اگر آپ کو اپنی کلاس میں متعدد کنسٹرکٹرز کی ضرورت ہے، بشمول بغیر دلیل کنسٹرکٹر، تو آپ کو الگ سے اس کا اعلان کرنا پڑے گا۔ مثال کے طور پر، فرض کریں کہ ہم ویٹرنری کلینک کے لیے ایک پروگرام بنا رہے ہیں۔ ہمارا کلینک اچھے کام کرنا اور بے گھر بلی کے بچوں کی مدد کرنا چاہتا ہے جن کے نام اور عمر نامعلوم ہیں۔ پھر ہمارا کوڈ اس طرح نظر آنا چاہئے:
public class Cat {

   String name;
   int age;

   // For cats with owners
   public Cat(String name, int age) {
       this.name = name;
       this.age = age;
   }

   // For street cats
   public Cat() {
   }

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 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 smudge = new Cat("Smudge", 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("It was founded " + this.age + " years ago" );
   System.out.println("Since that time, it has produced " + this.carsCount +  " cars");
   System.out.println("On average, it produces " + (this.carsCount/this.age) + " cars per year");
}

   public static void main(String[] args) {

       CarFactory ford = new CarFactory("Ford", 115 , 50000000);
   }
}
ہمارے پاس کار فیکٹری کی کلاس ہے جو کار فیکٹری کی وضاحت کرتی ہے۔ کنسٹرکٹر کے اندر، ہم تمام فیلڈز کو شروع کرتے ہیں اور کچھ منطق شامل کرتے ہیں: ہم فیکٹری کے بارے میں کچھ معلومات ظاہر کرتے ہیں۔ ایسا لگتا ہے کہ اس میں کوئی بری بات نہیں ہے۔ پروگرام ٹھیک کام کرتا ہے۔ کنسول آؤٹ پٹ: ہماری کار فیکٹری کو فورڈ کہا جاتا ہے اس کی بنیاد 115 سال پہلے رکھی گئی تھی اس وقت سے اب تک اس نے 50000000 کاریں تیار کی ہیں اوسطاً، یہ ہر سال 434782 کاریں تیار کرتی ہے لیکن ہم نے درحقیقت ایک وقتی تاخیر والی مائن بچھائی ہے۔ اور اس قسم کا کوڈ بہت آسانی سے غلطیوں کا باعث بن سکتا ہے۔ فرض کریں کہ اب ہم فورڈ کے بارے میں نہیں بلکہ ایک نئی فیکٹری کے بارے میں بات کر رہے ہیں جس کا نام "امیگو موٹرز" ہے، جو ایک سال سے بھی کم عرصے سے موجود ہے اور اس نے 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 factor is called " + this.name);
   System.out.println("It was founded " + this.age + " years ago" );
   System.out.println("Since that time, it has produced " + this.carsCount +  " cars");
   System.out.println("On average, it 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 کاریں تیار کی ہیں۔ (CarFactory.java:15) CarFactory.main (CarFactory.java:23) پر عمل ایگزٹ کوڈ 1 کے ساتھ ختم ہوا۔ بوم! پروگرام کسی قسم کی ناقابل فہم غلطی کے ساتھ ختم ہوتا ہے۔ کیا آپ وجہ کا اندازہ لگانے کی کوشش کر سکتے ہیں؟ مسئلہ اس منطق میں ہے جو ہم کنسٹرکٹر میں ڈالتے ہیں۔ مزید خاص طور پر، یہ لائن:
System.out.println("On average, it 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