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

آبجیکٹ اورینٹڈ پروگرامنگ (OOP) کیا ہے؟

یقیناً، جاوا صرف تفریح ​​کے لیے اشیاء اور کلاسوں پر مشتمل نہیں ہے۔ وہ جاوا کے تخلیق کاروں کی خواہش نہیں ہیں، اور ان کی ایجاد بھی نہیں۔ اشیاء پر مبنی بہت سی دوسری زبانیں ہیں۔ اس طرح کی پہلی زبان "سمولا" کہلاتی تھی۔ اس کی ایجاد 1960 کی دہائی میں ناروے میں ہوئی تھی۔ مزید یہ کہ سمولا میں "کلاس" اور "طریقہ" کے تصورات سامنے آئے۔ سافٹ ویئر ڈویلپمنٹ کے معیارات کے مطابق، "سمولا" ایک قدیم زبان کی طرح لگتا ہے، لیکن کوئی بھی جاوا کے ساتھ اس کی "خاندانی مماثلت" دیکھ سکتا ہے۔ آبجیکٹ اورینٹڈ پروگرامنگ کے اصول - 1آپ شاید اس زبان میں لکھے گئے کوڈ کو آسانی سے پڑھ سکتے ہیں اور وسیع اسٹروک میں وضاحت کر سکتے ہیں کہ یہ کیا کرتا ہے :)
Begin
	Class Rectangle (Width, Height); Real Width, Height;

	 Begin
	    Real Area, Perimeter;

	    Procedure Update;
	    Begin
	      Area := Width * Height;
              OutText("Rectangle is updating, Area = "); OutFix(Area,2,8); OutImage;
	      Perimeter := 2*(Width + Height);
              OutText("Rectangle is updating, Perimeter = "); OutFix(Perimeter,2,8); OutImage;
	    End of Update;

	    Update;
	    OutText("Rectangle created: "); OutFix(Width,2,6);
	    OutFix(Height,2,6); OutImage;
	 End of Rectangle;

       Rectangle Class ColouredRectangle (Color); Text Color;

	Begin
	    OutText("ColouredRectangle created, color = "); OutText(Color);
	    OutImage;
        End of ColouredRectangle;


      	 Ref(Rectangle) Cr;
	 Cr :- New ColouredRectangle(10, 20, "Green");
End;
یہ کوڈ نمونہ کوڈ Weekly-geekly کی طرف سے "Simula - OOP کے 50 سال" سے لیا گیا تھا۔ جیسا کہ آپ دیکھ سکتے ہیں، جاوا اپنے دادا سے اتنا مختلف نہیں ہے :) یہ اس حقیقت کی وجہ سے ہے کہ سمولا کی ظاہری شکل نے ایک نئے تصور کی پیدائش کا نشان لگایا: آبجیکٹ پر مبنی پروگرامنگ۔ ویکیپیڈیا OOP کی تعریف اس طرح کرتا ہے: "آبجیکٹ اورینٹڈ پروگرامنگ (OOP) ایک پروگرامنگ پیراڈائم ہے جس کی بنیاد "آبجیکٹ" کے تصور پر ہے، جس میں ڈیٹا ہو سکتا ہے، فیلڈز (اکثر اوصاف کے نام سے جانا جاتا ہے)، اور کوڈ کی شکل میں۔ طریقہ کار (اکثر طریقوں کے نام سے جانا جاتا ہے)۔" میری رائے میں، یہ واقعی ایک اچھی تعریف ہے۔ ابھی زیادہ عرصہ نہیں گزرا تھا کہ آپ نے جاوا سیکھنا شروع کیا تھا، لیکن اس تعریف میں شاید ایسے الفاظ شامل نہیں ہیں جو آپ نہیں جانتے ہوں :) آج OOP پروگرامنگ کا سب سے عام طریقہ کار ہے۔ جاوا کے علاوہ، OOP اصول بہت سی مشہور زبانوں میں استعمال ہوتے ہیں جن کے بارے میں آپ نے سنا ہوگا۔ مثال کے طور پر، C++ (گیم ڈویلپمنٹ میں فعال طور پر استعمال کیا جاتا ہے)، آبجیکٹو-سی اور سوئفٹ (ایپل ڈیوائسز کے لیے پروگرام لکھنے کے لیے استعمال کیا جاتا ہے)، ازگر (مشین لرننگ میں سب سے زیادہ مقبول)، پی ایچ پی (ایک مقبول ویب ڈویلپمنٹ لینگوئجز)، جاوا اسکرپٹ ( یہ کہنا آسان ہے کہ یہ کس چیز کے لیے استعمال نہیں کیا جاتا ہے) اور بہت سے دوسرے۔ تو، ویسے بھی OOP کے اصول کیا ہیں؟ ہم آپ کو تفصیل سے بتائیں گے۔

OOP اصول

یہ فاؤنڈیشن کی بنیاد ہیں۔ 4 اہم خصوصیات جو مل کر آبجیکٹ اورینٹڈ پروگرامنگ پیراڈائم بناتے ہیں۔ ان کو سمجھنا ایک کامیاب پروگرامر بننے کے لیے ضروری ہے۔

اصول 1. وراثت

اچھی خبر: آپ OOP کے کچھ اصول پہلے ہی جانتے ہیں! :) ہم نے پہلے ہی اسباق میں ایک دو بار وراثت کا سامنا کیا ہے، اور ہم اسے استعمال کرنے میں کامیاب ہو گئے۔ وراثت ایک ایسا طریقہ کار ہے جو آپ کو موجودہ (والدین) کلاس کی بنیاد پر ایک نئی کلاس کی وضاحت کرنے دیتا ہے۔ ایسا کرنے میں، نئی کلاس پیرنٹ کلاس کی خصوصیات اور فعالیت کو مستعار لیتی ہے۔ وراثت کس کے لیے ہے اور اس سے کیا فوائد حاصل ہوتے ہیں؟ سب سے بڑھ کر، کوڈ کو دوبارہ استعمال کریں۔ پیرنٹ کلاسز میں اعلان کردہ فیلڈز اور طریقے ڈیسنڈنٹ کلاسز میں استعمال کیے جا سکتے ہیں۔ اگر تمام قسم کی کاروں میں 10 عام فیلڈز اور 5 ایک جیسے طریقے ہیں، تو آپ کو بس انہیں آٹو پیرنٹ کلاس میں منتقل کرنے کی ضرورت ہے۔ آپ انہیں بغیر کسی پریشانی کے نسلی کلاسوں میں استعمال کرسکتے ہیں۔ ٹھوس فوائد: دونوں مقداری (کم کوڈ) اور نتیجے کے طور پر، کوالٹیٹیو (کلاسز بہت آسان ہو جاتی ہیں)۔ مزید برآں، وراثت بہت لچکدار ہے — آپ لکھنے کی الگ فعالیت شامل کر سکتے ہیں جو کہ اولاد غائب ہے (کچھ فیلڈز یا طرز عمل جو کسی خاص طبقے کے لیے مخصوص ہیں)۔ عام طور پر، جیسا کہ حقیقی زندگی میں، ہم سب اپنے والدین سے کسی حد تک ملتے جلتے ہیں، لیکن کسی نہ کسی طرح ان سے مختلف بھی ہیں :)

اصول 2. خلاصہ

یہ بہت سادہ اصول ہے۔ تجرید کا مطلب ہے کسی چیز کی اہم، اہم ترین خصوصیات کی نشاندہی کرنا، جبکہ بیک وقت کسی بھی معمولی اور غیر اہم چیز کو ترک کرنا۔ پہیے کو دوبارہ ایجاد کرنے کی ضرورت نہیں ہے۔ آئیے کلاسوں کے بارے میں ایک پرانے سبق سے ایک مثال یاد کرتے ہیں۔ فرض کریں کہ ہم کمپنی کے ملازمین کے لیے فائلنگ سسٹم بنا رہے ہیں۔ "ملازم" اشیاء بنانے کے لیے، ہم نے ایک ملازم کلاس لکھی ہے۔ کمپنی فائلنگ سسٹم میں ان کی وضاحت کے لیے کون سی خصوصیات اہم ہیں؟ نام، تاریخ پیدائش، SSN، اور ملازم کی شناخت۔ لیکن اس کا امکان نہیں ہے کہ ہمیں اس قسم کے ریکارڈ کے لیے ملازم کی قد، آنکھوں کا رنگ، یا بالوں کا رنگ درکار ہو۔ کمپنی کو کسی ملازم کے بارے میں ایسی معلومات کی ضرورت نہیں ہے۔ لہذا، ایمپلائی کلاس میں، ہم درج ذیل متغیرات کا اعلان کرتے ہیں: اسٹرنگ کا نام ، int عمر ، int socialSecurityNumber ، اور int employeeId ۔ اور ہم آنکھوں کا رنگ جیسی غیر ضروری معلومات کو ختم کر دیتے ہیں۔ تاہم، اگر ہم ماڈلنگ ایجنسی کے لیے فائلنگ سسٹم بنا رہے ہیں، تو صورتحال ڈرامائی طور پر بدل جاتی ہے۔ ماڈل کی اونچائی، آنکھوں کا رنگ، اور بالوں کا رنگ اہم خصوصیات ہیں، لیکن اس کا SSN ہمارے لیے بالکل غیر متعلق ہے۔ لہذا، ماڈل کلاس میں، ہم درج ذیل متغیرات بناتے ہیں: String height , String hair , String eyes ۔

اصول 3. انکیپسولیشن

ہم پہلے ہی اس میں بھاگ چکے ہیں۔ جاوا میں، encapsulation کا مطلب ہے ڈیٹا کو پڑھنے اور تبدیل کرنے کی صلاحیت کو محدود کرنا۔ جیسا کہ آپ دیکھ سکتے ہیں، اصطلاح لفظ "کیپسول" پر مبنی ہے. ہم کچھ اہم ڈیٹا کو چھپانے کے لیے ایک "کیپسول" استعمال کریں گے جسے ہم نہیں چاہتے کہ دوسرے تبدیل کریں۔ یہاں حقیقی زندگی سے ایک سادہ سی مثال ہے۔ آپ کا پہلا نام اور آخری نام ہے۔ آپ کے تمام دوست انہیں جانتے ہیں۔ لیکن ان میں آپ کا پہلا یا آخری نام تبدیل کرنے کی اہلیت نہیں ہے۔ ہم کہہ سکتے ہیں کہ ایسا کرنے کا عمل عدالتی نظام کے ذریعے "انکیپسلیٹڈ" ہے: آپ اپنا آخری نام صرف عدالت کے کلرک کے ذریعے تبدیل کر سکتے ہیں، اور صرف آپ ہی کر سکتے ہیں۔ دوسرے "صارفین" کو آپ کے پہلے اور آخری نام تک "صرف پڑھنے کے لیے" رسائی حاصل ہے :) ایک اور مثالی مثال گھر میں رکھی گئی نقدی ہے۔ اسے اپنے کمرے کے بیچ میں صاف نظر میں چھوڑنا اچھا خیال نہیں ہے۔ کوئی بھی "صارف" (وہ شخص جو آپ کے گھر آتا ہے) آپ کے پیسے کی رقم تبدیل کر سکے گا، یعنی وہ آپ کے پیسے لے سکتا ہے۔ بہتر ہو گا کہ اسے کسی سیف میں سمیٹ لیا جائے۔ تب رسائی صرف آپ کو اور صرف ایک خاص کوڈ کے ذریعے دستیاب ہوگی۔ انکیپسولیشن کی واضح مثالیں جن کے ساتھ آپ پہلے ہی کام کر چکے ہیں رسائی میں ترمیم کرنے والے (نجی، عوامی، وغیرہ) کے ساتھ ساتھ سیٹرز اور حاصل کرنے والے ہیں۔ اگر آپ کیٹ کلاس کی عمر کے فیلڈ کو شامل نہیں کرتے ہیں ، تو کوئی بھی لکھ سکتا ہے:
Cat.age = -1000;
انکیپسولیشن میکانزم ہمیں سیٹر کے طریقہ کار کے ساتھ عمر کے میدان کی حفاظت کرنے دیتا ہے، جہاں ہم اس بات کو یقینی بنا سکتے ہیں کہ عمر کو منفی نمبر پر سیٹ نہیں کیا جا سکتا۔

اصول 4. پولیمورفزم

پولیمورفزم کئی اقسام کے ساتھ کام کرنے کی صلاحیت ہے جیسے کہ وہ ایک ہی قسم کے ہوں۔ مزید یہ کہ اشیاء کا طرز عمل ان کی قسم کے لحاظ سے مختلف ہوگا۔ کیا یہ پیچیدہ لگتا ہے؟ آئیے ابھی اس کا احساس کریں۔ سب سے آسان مثال لیں: جانور۔ ایک ہی اسپیک() طریقہ کے ساتھ اینیمل کلاس بنائیں ، اور دو ذیلی کلاسز — Cat اور Dog ۔
public class Animal {

   public void speak() {

       System.out.println("Hello!");
   }
}

public class Dog extends Animal {

   @Override
   public void speak() {
       System.out.println ("Woof-woof!");
   }
}

public class Cat extends Animal {

   @Override
   public void speak() {
       System.out.println("Meow!");
   }
}
اب ہم کوشش کریں گے کہ ایک اینیمل ریفرنس متغیر کا اعلان کریں اور اس پر ایک کتے کی چیز تفویض کریں۔
public class Main {

   public static void main(String[] args) {

       Animal dog = new Dog();
       dog.speak();
   }
}
آپ کے خیال میں کیا طریقہ کہا جائے گا؟ Animal.speak() یا Dog.speak() ؟ ڈاگ کلاس میں طریقہ کو کہا جائے گا: Woof-woof! ہم نے جانوروں کا حوالہ بنایا، لیکن شے کتے کی طرح برتاؤ کرتی ہے ۔ اگر ضروری ہو تو، یہ ایک بلی، گھوڑے، یا کسی دوسرے جانور کی طرح برتاؤ کر سکتا ہے۔ اہم بات یہ ہے کہ عام جانوروں کے حوالہ متغیر کو ایک مخصوص ذیلی طبقے کو تفویض کیا جائے۔ یہ سمجھ میں آتا ہے، کیونکہ تمام کتے جانور ہیں۔ یہ وہی ہے جو ہمارے ذہن میں تھا جب ہم نے کہا کہ "اشیا کا طرز عمل ان کی قسم کے لحاظ سے مختلف ہوگا۔" اگر ہم نے ایک بلی آبجیکٹ بنایا...
public static void main(String[] args) {

   Animal cat = new Cat();
   cat.speak();
}
اسپیک () طریقہ "میاؤ!" ظاہر کرے گا۔ لیکن 'کئی اقسام کے ساتھ کام کرنے کی صلاحیت جیسے کہ وہ ایک ہی قسم کے ہوں' سے ہمارا کیا مطلب ہے؟ یہ بھی کافی سیدھی بات ہے۔ آئیے تصور کریں کہ ہم جانوروں کے لیے ایک حجام کی دکان بنا رہے ہیں۔ ہماری حجام کی دکان کو کسی بھی جانور کو ٹرم دینے کے قابل ہونا چاہئے، لہذا ہم جانوروں کے پیرامیٹر (جانور کے بال کٹوانے) کے ساتھ ایک trim() طریقہ بناتے ہیں۔
public class AnimalBarbershop {

   public void trim(Animal animal) {

       System.out.println("The haircut is done!");
   }
}
اور اب ہم بلی اور کتے کی اشیاء کو trim() طریقہ پر منتقل کر سکتے ہیں !
public static void main(String[] args) {

   Cat cat = new Cat();
   Dog dog = new Dog();

   AnimalBarbershop barbershop = new AnimalBarbershop();

   barbershop.trim(cat);
   barbershop.trim(dog);
}
اور یہاں واضح مثال ہے: اینیمل باربر شاپ کلاس بلی اور کتے کی اقسام کے ساتھ اس طرح کام کرتی ہے جیسے وہ ایک ہی قسم کے ہوں۔ ایک ہی وقت میں، بلی اور کتے کے رویے مختلف ہیں: وہ ہر ایک مختلف طریقے سے بولتے ہیں.

ہمیں OOP کی ضرورت کیوں ہے؟

OOP کبھی بھی ایک نئے پروگرامنگ تصور کے طور پر کیوں پیدا ہوا؟ پروگرامرز کے پاس کام کرنے والے ٹولز تھے، جیسے کہ طریقہ کار کی زبانیں۔ کس چیز نے انہیں بنیادی طور پر کوئی نئی چیز ایجاد کرنے پر اکسایا؟ سب سے بڑھ کر ان کاموں کی پیچیدگی جس کا انہیں سامنا کرنا پڑا۔ اگر 60 سال پہلے پروگرامر کا کام کچھ ایسا ہوتا تھا جیسے "کچھ ریاضیاتی اظہار کا اندازہ لگانا"، اب یہ کچھ ایسا ہو سکتا ہے جیسے "گیم STALKER کے لیے 7 مختلف اختتامات کو لاگو کرنا، پوائنٹس A، B، C، DE پر کیے گئے کھلاڑی کے فیصلوں کے مجموعے پر منحصر ہے۔ ، اور کھیل میں ایف۔" جیسا کہ آپ دیکھ سکتے ہیں، کام واضح طور پر پچھلی دہائیوں میں زیادہ پیچیدہ ہو گئے ہیں۔ اور نتیجے کے طور پر، ڈیٹا کی اقسام زیادہ پیچیدہ ہو گئی ہیں. یہ ایک اور وجہ ہے کہ OOP ظاہر ہوا۔ ایک ریاضیاتی اظہار کو عام پرائمیٹوز کا استعمال کرتے ہوئے آسانی سے جانچا جا سکتا ہے۔ یہاں کسی چیز کی ضرورت نہیں ہے۔ لیکن گیم ختم ہونے والے کام کو حسب ضرورت کلاسز استعمال کیے بغیر بیان کرنا بھی مشکل ہوگا۔ اس نے کہا، کلاسوں اور اشیاء کا استعمال کرتے ہوئے اسے بیان کرنا کافی آسان ہے۔ ظاہر ہے، ہمیں کئی کلاسز کی ضرورت ہوگی: گیم، اسٹاکر، اینڈنگ، پلیئر ڈیسیژن، گیم ایونٹ، وغیرہ۔ دوسرے لفظوں میں، یہاں تک کہ مسئلے کو حل کرنا شروع کیے بغیر، ہم آسانی سے اپنے سر میں کوئی حل نکال سکتے ہیں۔ کاموں کی بڑھتی ہوئی پیچیدگی نے پروگرامرز کو انہیں حصوں میں تقسیم کرنے پر مجبور کیا۔ لیکن پروسیجرل پروگرامنگ میں ایسا کرنا اتنا آسان نہیں تھا۔ اور اکثر ایک پروگرام ایک درخت کی طرح ہوتا تھا جس میں بہت سی شاخیں ہوتی ہیں جو عمل درآمد کے تمام ممکنہ راستوں کی نمائندگی کرتی ہیں۔ کچھ شرائط پر منحصر ہے، پروگرام کی ایک شاخ یا دوسری کو پھانسی دی گئی تھی۔ چھوٹے پروگراموں کے لیے یہ آسان تھا، لیکن ایک بڑے مسئلے کو حصوں میں تقسیم کرنا بہت مشکل تھا۔ یہ OOP کے ابھرنے کی ایک اور وجہ تھی۔ اس تمثیل نے پروگرامرز کو ایک پروگرام کو "ماڈیولز" (کلاسز) کے ایک گروپ میں تقسیم کرنے کی صلاحیت دی، جن میں سے ہر ایک اپنے کام کا حصہ خود کرتا ہے۔ ایک دوسرے کے ساتھ بات چیت کرکے، تمام اشیاء ہمارے پروگرام کے کام کو پورا کرتی ہیں۔ اس کے علاوہ، ہم اپنے کوڈ کو پروگرام میں کسی اور جگہ دوبارہ استعمال کر سکتے ہیں، جس سے کافی وقت بھی بچتا ہے۔