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

    String name;
    int age;

    public void sayMeow() {
        System.out.println("Meow!");
    }

    public void jump() {
        System.out.println("Pounce!");
    }

    public static void main(String[] args) {
        Cat smudge = new Cat();
        smudge.age = 3;
        smudge.name = "Smudge";

        smudge.sayMeow();
        smudge.jump();
    }
}
sayMeow() اور jump() ہماری کلاس کے طریقے ہیں۔ اور ان طریقوں کو چلانے کے نتیجے میں درج ذیل کنسول آؤٹ پٹ ہوتے ہیں۔
Meow!
Pounce!
ہمارے طریقے کافی آسان ہیں: وہ صرف کنسول میں ٹیکسٹ آؤٹ پٹ کرتے ہیں۔ لیکن جاوا میں، طریقوں کا ایک اہم کام ہے: وہ کسی چیز کے ڈیٹا پر کارروائیاں کرتے ہیں۔ وہ آبجیکٹ کے ڈیٹا کو تبدیل کرتے ہیں، اسے تبدیل کرتے ہیں، اسے ڈسپلے کرتے ہیں، اور اس کے ساتھ دیگر کام کرتے ہیں۔ ہمارے موجودہ طریقے کیٹ آبجیکٹ کے ڈیٹا کے ساتھ کچھ نہیں کرتے ۔ آئیے ایک اور مثالی مثال دیکھیں:
public class Truck {

    int length;
    int width;
    int height;
    int weight;

    public int getVolume() {
        int volume = length * width * height;
        return volume;
    }
}
مثال کے طور پر، یہاں ہمارے پاس ایک کلاس ہے جو ٹرک کی نمائندگی کرتی ہے ۔ نیم ٹرک کی لمبائی، چوڑائی، اونچائی اور وزن ہے (جس کی ہمیں بعد میں ضرورت ہوگی)۔ getVolume() طریقہ میں ، ہم اپنے آبجیکٹ کے ڈیٹا کو اس کے حجم کی نمائندگی کرنے والے نمبر میں تبدیل کرتے ہوئے حساب لگاتے ہیں (ہم لمبائی، چوڑائی اور اونچائی کو ضرب دیتے ہیں)۔ یہ نمبر طریقہ کار کا نتیجہ ہوگا۔ نوٹ کریں کہ طریقہ کا اعلان پبلک int getVolume کے طور پر لکھا گیا ہے ۔ اس کا مطلب یہ ہے کہ اس طریقہ کو ایک int واپس کرنا ہوگا ۔ ہم نے طریقہ کی واپسی کی قیمت کا حساب لگایا، اور اب ہمیں اسے اس پروگرام میں واپس کرنا ہوگا جس نے ہمارا طریقہ کہا ہے۔ جاوا میں طریقہ کا نتیجہ واپس کرنے کے لیے، ہم مطلوبہ الفاظ کی واپسی کا استعمال کرتے ہیں۔ واپسی کا حجم؛

جاوا طریقہ پیرامیٹرز

ہم "دلائل" نامی اقدار کو کسی طریقہ پر کال کرتے وقت منتقل کر سکتے ہیں۔ طریقہ کے اعلان میں متغیرات کی ایک فہرست شامل ہوتی ہے جو ہمیں متغیر کی قسم اور ترتیب بتاتی ہے جسے طریقہ قبول کر سکتا ہے۔ اس فہرست کو "طریقہ پیرامیٹرز" کہا جاتا ہے۔ ہماری ٹرک کلاس کا getVolume() طریقہ فی الحال کسی بھی پیرامیٹرز کی وضاحت نہیں کرتا، تو آئیے اپنے ٹرک کی مثال کو بڑھانے کی کوشش کریں۔ BridgeOfficer کے نام سے ایک نئی کلاس بنائیں ۔ یہ ایک پل پر ڈیوٹی پر مامور پولیس افسر ہے، جو گزرنے والے تمام ٹرکوں کو یہ دیکھنے کے لیے چیک کرتا ہے کہ آیا ان کا بوجھ اجازت شدہ وزن سے زیادہ ہے۔
public class BridgeOfficer {

    int maxWeight;

    public BridgeOfficer(int normalWeight) {
        this.maxWeight = normalWeight;
    }

    public boolean checkTruck(Truck truck) {
        if (truck.weight > maxWeight) {
            return false;
        } else {
            return true;
        }
    }
}
چیک ٹرک کا طریقہ ایک دلیل، ٹرک آبجیکٹ کو قبول کرتا ہے، اور یہ طے کرتا ہے کہ آیا افسر ٹرک کو پل پر جانے کی اجازت دے گا یا نہیں۔ طریقہ کار کے اندر، منطق کافی آسان ہے: اگر ٹرک کا وزن زیادہ سے زیادہ اجازت شدہ حد سے زیادہ ہے، تو طریقہ غلط واپس آتا ہے ۔ اسے دوسری سڑک تلاش کرنی پڑے گی :( اگر وزن زیادہ سے زیادہ سے کم یا اس کے برابر ہے، تو یہ گزر سکتا ہے، اور طریقہ درست ہو جاتا ہے۔ قدر" ابھی تک، آئیے پروگرامنگ سے وقفہ لیں اور حقیقی زندگی سے ایک سادہ سی مثال استعمال کرتے ہوئے ان پر غور کریں۔ :) مان لیں کہ آپ بیمار ہو جاتے ہیں اور کچھ دن کام سے گھر پر رہتے ہیں۔ آپ اپنے ڈاکٹر کے نوٹ کے ساتھ اکاؤنٹنگ ڈپارٹمنٹ میں جائیں، کیونکہ بیماری کی چھٹی ادا کی جانی ہے۔ اگر ہم اس صورتحال کا موازنہ طریقوں سے کریں، تو اکاؤنٹنٹ کے پاس paySickLeave() طریقہ ہے۔ آپ اس طریقہ کی دلیل کے طور پر ڈاکٹر کا نوٹ پاس کرتے ہیں (اس کے بغیر یہ طریقہ کام نہیں کرے گا اور آپ کو معاوضہ نہیں ملے گا!) اس کے بعد آپ کے نوٹ کا استعمال کرتے ہوئے طریقہ کار کے اندر ضروری حسابات کیے جاتے ہیں (اکاؤنٹنٹ اسے استعمال کرتا ہے کہ کمپنی آپ کو کتنی رقم ادا کرے)، اور آپ کے کام کا نتیجہ (رقم کی رقم) آپ کو واپس کر دی جاتی ہے۔ ہمارا پروگرام اسی طرح کام کرتا ہے۔ یہ ایک طریقہ کو کال کرتا ہے، اس میں ڈیٹا منتقل کرتا ہے، اور بالآخر نتیجہ حاصل کرتا ہے۔ ہمارے BridgeOfficer پروگرام کا مین() طریقہ یہ ہے:
public static void main(String[] args) {
    Truck first = new Truck();
    first.weight = 10000;
    Truck second = new Truck();
    second.weight = 20000;

    BridgeOfficer officer = new BridgeOfficer(15000);
    System.out.println("Truck 1! Can I go, officer?");
    boolean canFirstTruckGo = officer.checkTruck(first);
    System.out.println(canFirstTruckGo);

    System.out.println();

    System.out.println("Truck 2! And can I?");
    boolean canSecondTruckGo = officer.checkTruck(second);
    System.out.println(canSecondTruckGo);
}
ہم 10,000 اور 20,000 کے بوجھ کے ساتھ دو ٹرک بناتے ہیں۔ اور جس پل پر افسر کام کرتا ہے اس کا زیادہ سے زیادہ وزن 15000 ہے۔ پروگرام آفیسر چیک ٹرک (پہلا) طریقہ کہتا ہے۔ طریقہ ہر چیز کا حساب لگاتا ہے اور پھر واپس آتا ہے true ، جسے پروگرام پھر بولین متغیر canFirstTruckGo میں محفوظ کرتا ہے ۔ اب آپ اس کے ساتھ جو چاہیں کر سکتے ہیں (جیسے آپ اکاؤنٹنٹ کے دیے گئے پیسوں سے کر سکتے ہیں)۔ دن کے اختتام پر، کوڈ
boolean canFirstTruckGo = officer.checkTruck(first);
تک ابلتا ہے
boolean canFirstTruckGo =  true;
یہاں ایک بہت اہم نکتہ ہے: واپسی کا بیان صرف طریقہ کی واپسی کی قیمت نہیں لوٹاتا ہے، یہ طریقہ کو چلنے سے بھی روکتا ہے! کوئی بھی کوڈ جو واپسی کے بیان کے بعد آتا ہے اس پر عمل نہیں کیا جائے گا!
public boolean checkTruck(Truck truck) {

    if (truck.weight > maxWeight) {
        return false;
        System.out.println("Turn around, you're overweight!");
    } else {
        return true;
        System.out.println("Everything looks good, go ahead!");
    }
}
افسر کے تبصرے ظاہر نہیں کیے جائیں گے، کیونکہ طریقہ پہلے ہی نتیجہ واپس کر چکا ہے اور ختم کر دیا گیا ہے! پروگرام اس جگہ پر واپس آجاتا ہے جہاں طریقہ بلایا گیا تھا۔ آپ کو اس کے لیے دیکھنے کی ضرورت نہیں ہے: جاوا کمپائلر اتنا ہوشیار ہے کہ جب آپ واپسی کے بیان کے بعد کوڈ لکھنے کی کوشش کرتے ہیں تو غلطی پیدا کر سکتی ہے۔

ایونجرز: پیرامیٹر وار

ایسے حالات ہیں جب ہم ایک طریقہ کو کال کرنے کے کئی طریقے چاہیں گے۔ اپنی مصنوعی ذہانت کیوں نہ بنائیں؟ ایمیزون کے پاس الیکسا ہے، ایپل کے پاس سری ہے، تو ہمارے پاس کیوں نہیں ہونا چاہئے؟ :) فلم آئرن مین میں، ٹونی سٹارک اپنی ناقابل یقین مصنوعی ذہانت، جارویس تخلیق کرتا ہے۔ آئیے اس شاندار کردار کو خراج تحسین پیش کریں اور اس کے اعزاز میں اپنے AI کا نام رکھیں۔ :) سب سے پہلے ہمیں جارویس کو کمرے میں داخل ہونے والے لوگوں کو ہیلو کہنا سکھانا ہے (اگر ایسی حیرت انگیز عقل غیر اخلاقی نکلے تو یہ عجیب بات ہوگی)۔
public class Jarvis {

    public void sayHi(String name) {
        System.out.println("Good evening, " + name + ". How are you?");
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark");
    }
}
کنسول آؤٹ پٹ:
Good evening, Tony Stark. How are you?
بہت اچھا! جارویس اب مہمانوں کا استقبال کرنے کے قابل ہے۔ یقینا، زیادہ کثرت سے یہ اس کا ماسٹر ٹونی اسٹارک ہوگا۔ لیکن اگر وہ اکیلا نہ آئے تو کیا ہوگا! ہمارا sayHi() طریقہ صرف ایک دلیل کو قبول کرتا ہے۔ اور اس طرح یہ کمرے میں داخل ہونے والے صرف ایک شخص کو سلام کر سکتا ہے، اور دوسرے کو نظر انداز کر دے گا۔ بہت شائستہ نہیں، کیا آپ متفق نہیں ہیں؟ :/

جاوا طریقہ اوورلوڈنگ

اس صورت میں، ہم صرف ایک ہی نام کے ساتھ 2 طریقے لکھ کر مسئلہ حل کر سکتے ہیں، لیکن مختلف پیرامیٹرز:
public class Jarvis {

    public void sayHi(String firstGuest) {
        System.out.println("Good evening, " + firstGuest + ". How are you?");
    }

    public void sayHi(String firstGuest, String secondGuest) {
        System.out.println("Good evening, " + firstGuest + " and " + secondGuest + ". How are you?");
    }
}
اسے طریقہ اوورلوڈنگ کہتے ہیں۔ طریقہ اوورلوڈنگ ہمارے پروگرام کو زیادہ لچکدار اور کام کرنے کے مختلف طریقوں کو ایڈجسٹ کرنے دیتا ہے۔ آئیے جائزہ لیں کہ یہ کیسے کام کرتا ہے:
public class Jarvis {

    public void sayHi(String firstGuest) {
        System.out.println("Good evening, " + firstGuest + ". How are you?");
    }

    public void sayHi(String firstGuest, String secondGuest) {
        System.out.println("Good evening, " + firstGuest + " and " + secondGuest + ". How are you?");
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark");
        jarvis.sayHi("Tony Stark", "Captain America");
    }
}
کنسول آؤٹ پٹ:
Good evening, Tony Stark. How are you?
Good evening, Tony Stark and Captain America. How are you?
بہت اچھا، دونوں ورژن نے کام کیا۔ :) لیکن ہم نے مسئلہ حل نہیں کیا! اگر تین مہمان ہوں تو کیا ہوگا؟ ہم یقیناً sayHi() طریقہ کو دوبارہ اوورلوڈ کر سکتے ہیں، تاکہ یہ تین مہمانوں کے ناموں کو قبول کرے۔ لیکن 4 یا 5 ہو سکتے ہیں۔ لامحدودیت تک۔ کیا لاکھوں بار sayHi() طریقہ کو اوورلوڈ کیے بغیر، جارویس کو کسی بھی نام کو سنبھالنا سکھانے کا کوئی بہتر طریقہ نہیں ہے ؟ :/ یقینا وہاں ہے! اگر ایسا نہ ہوتا تو کیا آپ کو لگتا ہے کہ جاوا دنیا کی سب سے مقبول پروگرامنگ لینگویج ہوگی؟ ;)
public void sayHi(String...names) {

    for (String name: names) {
        System.out.println("Good evening, " + name + ". How are you?");
    }
}
جب ( String... names ) کو پیرامیٹر کے طور پر استعمال کیا جاتا ہے، تو یہ اشارہ کرتا ہے کہ Strings کا ایک مجموعہ طریقہ میں منتقل کیا جائے گا۔ ہمیں پہلے سے بتانے کی ضرورت نہیں ہے کہ وہاں کتنے ہوں گے، لہذا اب ہمارا طریقہ بہت زیادہ لچکدار ہے:
public class Jarvis {

    public void sayHi(String...names) {
        for (String name: names) {
            System.out.println("Good evening, " + name + ". How are you?");
        }
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark", "Captain America", "Black Widow", "Hulk");
    }
}
کنسول آؤٹ پٹ:
Good evening, Tony Stark. How are you?
Good evening, Captain America. How are you?
Good evening, Black Widow. How are you?
Good evening, Hulk. How are you?
یہاں کچھ کوڈ آپ کے لیے ناواقف ہوں گے، لیکن اس کی فکر نہ کریں۔ یہ اس کے بنیادی طور پر آسان ہے: طریقہ ہر ایک کا نام بدل کر لیتا ہے اور ہر مہمان کو سلام کرتا ہے! اس کے علاوہ، یہ گزرے ہوئے تاروں کی کسی بھی تعداد کے ساتھ کام کرے گا! دو، دس، یہاں تک کہ ایک ہزار - یہ طریقہ کسی بھی مہمان کے ساتھ ٹھیک سے کام کرے گا۔ تمام امکانات کے لیے طریقہ کو اوور لوڈ کرنے سے کہیں زیادہ آسان، کیا آپ نہیں سوچتے؟ :) یہاں ایک اور اہم نکتہ ہے: دلائل کی ترتیب اہمیت رکھتی ہے! ہم کہتے ہیں کہ ہمارا طریقہ ایک سٹرنگ اور ایک نمبر لیتا ہے:
public class Person {

    public static void sayYourAge(String greeting, int age) {
        System.out.println(greeting + " " + age);
    }

    public static void main(String[] args) {
        sayYourAge("My age is ", 33);
        sayYourAge(33, "My age is "); // Error!
    }
}
اگر پرسن کلاس کا sayYourAge طریقہ ان پٹ کے طور پر ایک سٹرنگ اور ایک نمبر لیتا ہے، تو پروگرام کو انہیں اس مخصوص ترتیب میں پاس کرنا چاہیے! اگر ہم انہیں مختلف ترتیب سے پاس کرتے ہیں، تو مرتب کرنے والے میں ایک خرابی پیدا ہو جائے گی اور وہ شخص اپنی عمر نہیں بتا سکے گا۔ ویسے، کنسٹرکٹرز، جن کا ہم نے پچھلے سبق میں احاطہ کیا تھا، بھی طریقے ہیں! آپ ان کو اوورلوڈ بھی کر سکتے ہیں (یعنی پیرامیٹرز کے مختلف سیٹوں کے ساتھ کئی کنسٹرکٹرز بنائیں) اور پاس شدہ دلائل کی ترتیب ان کے لیے بھی بنیادی طور پر اہم ہے۔ وہ حقیقی طریقے ہیں! :)

پھر بھی پیرامیٹرز کے بارے میں

جی ہاں، معذرت، ہم نے ابھی تک ان کے ساتھ بات ختم نہیں کی ہے۔ :) اب ہم جس موضوع کا مطالعہ کریں گے وہ بہت اہم ہے۔ اس بات کا 90% امکان ہے کہ آئندہ ہر انٹرویو میں آپ سے اس بارے میں پوچھا جائے گا! آئیے طریقوں کو دلائل دینے کے بارے میں بات کرتے ہیں۔ ایک سادہ مثال پر غور کریں:
public class TimeMachine {

    public void goToFuture(int currentYear) {
        currentYear = currentYear+10;
    }

    public void goToPast(int currentYear) {
        currentYear = currentYear-10;
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        int currentYear = 2018;

        System.out.println("What year is it?");
        System.out.println(currentYear);

        timeMachine.goToPast(currentYear);
        System.out.println("How about now?");
        System.out.println(currentYear);
    }
}
ٹائم مشین کے دو طریقے ہیں۔ وہ دونوں موجودہ سال کی نمائندگی کرنے والے نمبر کو بطور ان پٹ لیتے ہیں، اور یا تو اس کی قدر میں اضافہ یا کمی کرتے ہیں (اس بات پر منحصر ہے کہ ہم ماضی میں جانا چاہتے ہیں یا مستقبل)۔ لیکن، جیسا کہ آپ کنسول آؤٹ پٹ سے دیکھ سکتے ہیں، طریقہ کام نہیں کرتا! کنسول آؤٹ پٹ:
What year is it?
2018
How about now?
2018
ہم نے موجودہ سال کے متغیر کو goToPast() طریقہ سے پاس کیا، لیکن اس کی قدر میں کوئی تبدیلی نہیں آئی۔ ہم 2018 میں تھے، اور ہم یہاں ٹھہرے ہیں۔ لیکن کیوں؟ :/ کیونکہ جاوا میں قدیم چیزوں کو قدر کے لحاظ سے طریقوں میں منتقل کیا جاتا ہے۔ اس کا کیا مطلب ہے؟ جب ہم goToPast() طریقہ کو کال کرتے ہیں اور اس میں int متغیر کرنٹ سال (=2018) پاس کرتے ہیں ، تو طریقہ خود موجودہ سال متغیر حاصل نہیں کرتا، بلکہ اس کی ایک کاپی حاصل کرتا ہے۔ بلاشبہ، اس کاپی کی قیمت بھی 2018 ہے، لیکن کاپی میں کوئی بھی تبدیلی ہمارے موجودہ موجودہ سال کے متغیر کو کسی بھی طرح متاثر نہیں کرتی ہے! آئیے اپنے کوڈ کو مزید واضح کریں اور دیکھتے ہیں کہ موجودہ سال کے ساتھ کیا ہوتا ہے:
public class TimeMachine {

    public void goToFuture(int currentYear) {
        currentYear = currentYear+10;
    }

    public void goToPast(int currentYear) {
        System.out.println("The goToPast method has started running!");
        System.out.println("currentYear inside the goToPast method (at the beginning) = " + currentYear);
        currentYear = currentYear-10;
        System.out.println("currentYear inside the goToPast method (at the end) = " + currentYear);
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        int currentYear = 2018;

        System.out.println("What was the year when the program started?");
        System.out.println(currentYear);

        timeMachine.goToPast(currentYear);
        System.out.println("And what year is it now?");
        System.out.println(currentYear);
    }
}
کنسول آؤٹ پٹ:
What was the year when the program started?
2018
The goToPast method has started running!
currentYear inside the goToPast method (at the beginning) = 2018
currentYear inside the goToPast method (at the end) = 2008
And what year is it now?
2018
یہ واضح طور پر ظاہر کرتا ہے کہ goToPast() طریقہ کو منتقل کیا گیا متغیر موجودہ سال کی صرف ایک نقل ہے ۔ اور کاپی کو تبدیل کرنے سے "اصل" قدر متاثر نہیں ہوتی۔ "حوالہ سے گزرنا" کا مطلب بالکل برعکس ہے۔ آئیے بلیوں پر مشق کریں! میرا مطلب ہے، آئیے دیکھتے ہیں کہ بلی کی مثال کا استعمال کرتے ہوئے حوالہ سے گزرنا کیسا لگتا ہے۔ :)
public class Cat {

    int age;

    public Cat(int age) {
        this.age = age;
    }
}
اب ہم اپنی ٹائم مشین کی مدد سے Smudge ، دنیا کی پہلی بار سفر کرنے والی بلی کو ماضی اور مستقبل میں بھیجیں گے! آئیے ٹائم مشین کلاس میں ترمیم کریں تاکہ یہ کیٹ اشیاء کے ساتھ کام کرے۔
public class TimeMachine {

    public void goToFuture(Cat cat) {
        cat.age += 10;
    }

    public void goToPast(Cat cat) {
        cat.age -= 10;
    }
}
اب طریقے صرف پاس شدہ نمبر کو تبدیل نہیں کرتے ہیں۔ بلکہ، وہ اس مخصوص بلی کی عمر کے میدان کو تبدیل کرتے ہیں۔ آپ کو یاد ہوگا کہ یہ ہمارے لیے پرائمیٹوز کے ساتھ کام نہیں کرتا تھا، کیونکہ اصل نمبر تبدیل نہیں ہوا تھا۔ دیکھتے ہیں کیا ہوتا ہے!
public static void main(String[] args) {

    TimeMachine timeMachine = new TimeMachine();
    Cat smudge = new Cat(5);

    System.out.println("How old was Smudge when the program started?");
    System.out.println(smudge.age);

    timeMachine.goToFuture(smudge);
    System.out.println("How about now?");
    System.out.println(smudge.age);

    System.out.println("Holy smokes! Smudge has aged 10 years! Back up quickly!");
    timeMachine.goToPast(smudge);
    System.out.println("Did it work? Have we returned the cat to its original age?");
    System.out.println(smudge.age);
}
کنسول آؤٹ پٹ:
How old was Smudge when the program started running?
5
How about now?
15
Holy smokes! Smudge has aged 10 years! Back up quickly!
Did it work? Have we returned the cat to its original age?
5
زبردست! اب طریقہ کار نے کچھ مختلف کیا: ہماری بلی کافی حد تک بوڑھی ہو گئی، لیکن پھر وہ دوبارہ جوان ہو گئی! :) آئیے اس کی وجہ جاننے کی کوشش کرتے ہیں۔ پرائمیٹوز کے ساتھ مثال کے برعکس، جب اشیاء کو کسی طریقہ پر منتقل کیا جاتا ہے تو وہ حوالہ سے گزر جاتے ہیں۔ اصل دھندلی آبجیکٹ کا حوالہ changeAge() طریقہ کو دیا گیا تھا۔ لہذا، جب ہم طریقہ کے اندر smudge.age کو تبدیل کرتے ہیں، تو ہم میموری کے اسی حصے کا حوالہ دے رہے ہیں جہاں ہمارا آبجیکٹ محفوظ ہے۔ یہ اسی Smudge کا حوالہ ہے جسے ہم نے شروع میں بنایا تھا۔ اسے کہتے ہیں "حوالہ سے گزرنا"! تاہم، حوالوں کے ساتھ سب کچھ اتنا آسان نہیں ہے۔ :) آئیے اپنی مثال کو تبدیل کرنے کی کوشش کریں:
public class TimeMachine {

    public void goToFuture(Cat cat) {
        cat = new Cat(cat.age);
        cat.age += 10;
    }

    public void goToPast(Cat cat) {
        cat = new Cat(cat.age);
        cat.age -= 10;
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        Cat smudge = new Cat(5);

        System.out.println("How old was Smudge when the program started?");
        System.out.println(smudge.age);

        timeMachine.goToFuture(smudge);
        System.out.println ("Smudge went to the future! Has his age changed?");
        System.out.println(smudge.age);

        System.out.println ("And if you try going back?");
        timeMachine.goToPast(smudge);
        System.out.println(smudge.age);
    }
}
کنسول آؤٹ پٹ:
How old was Smudge when the program started running?
5
Smudge went to the future! Has his age changed?
5
And if you try going back?
5
یہ دوبارہ کام نہیں کرتا! О_О آئیے معلوم کریں کہ کیا ہوا ہے۔ :) اس کا goToPast / goToFuture کے طریقوں اور حوالہ جات کے کام کرنے کے طریقہ سے سب کچھ ہے۔ اب، آپ کی توجہ، براہ مہربانی! یہ سمجھنے کے لیے سب سے اہم چیز ہے کہ حوالہ جات اور طریقے کیسے کام کرتے ہیں۔ حقیقت یہ ہے کہ جب ہم goToFuture(Cat cat) طریقہ کو کہتے ہیں، تو یہ بلی آبجیکٹ کے حوالے کی ایک کاپی ہے جو پاس ہو جاتی ہے، خود حوالہ نہیں۔ اس طرح، جب ہم کسی چیز کو کسی طریقہ میں منتقل کرتے ہیں، تو اس شے کے دو حوالے ہوتے ہیں۔ یہ سمجھنے کے لیے بہت اہم ہے کہ کیا ہو رہا ہے۔ یہی وجہ ہے کہ ہماری آخری مثال میں بلی کی عمر میں کوئی تبدیلی نہیں آئی۔ پچھلی مثال میں، عمر کو تبدیل کرتے وقت، ہم نے صرف goToFuture() طریقہ کار کے حوالے سے حوالہ لیا ، اور اسے میموری میں آبجیکٹ تلاش کرنے اور اس کی عمر ( cat.age += 10 ) کو تبدیل کرنے کے لیے استعمال کیا۔ لیکن اب، goToFuture() طریقہ کے اندر، ہم ایک نئی آبجیکٹ ( cat = new Cat(cat.age) ) بنا رہے ہیں، اور اس آبجیکٹ کو وہی حوالہ کاپی تفویض کیا گیا ہے جو طریقہ کو پاس کیا گیا تھا۔ اس کے نتیجے میں:
  • پہلا حوالہ ( Cat smudge = new Cat (5) ) اصل بلی کی طرف اشارہ کرتا ہے (5 سال کی عمر کے ساتھ)
  • اس کے بعد، جب ہم نے cat variable کو goToPast() طریقہ پاس کیا اور اسے ایک نیا آبجیکٹ تفویض کیا، تو حوالہ کاپی ہو گیا۔
اور اس نے ہمیں حتمی نتیجہ تک پہنچایا: دو حوالہ جات جو دو مختلف اشیاء کی طرف اشارہ کرتے ہیں۔ لیکن ہم نے صرف ان میں سے ایک کی عمر کو تبدیل کیا (جو طریقہ کے اندر بنایا گیا)۔
cat.age += 10;
اور ظاہر ہے، main() طریقہ میں ہم کنسول پر دیکھ سکتے ہیں کہ بلی کی عمر، smudge.age ، تبدیل نہیں ہوئی ہے۔ بہر حال، smudge ایک حوالہ متغیر ہے جو اب بھی 5 سال کی عمر کے ساتھ پرانی، اصل چیز کی طرف اشارہ کرتا ہے، اور ہم نے اس چیز کے ساتھ کچھ نہیں کیا۔ ہماری عمر کی تمام تبدیلیاں نئی ​​چیز پر کی گئیں۔ لہذا، یہ پتہ چلتا ہے کہ اشیاء کو حوالہ کے ذریعہ طریقوں میں منتقل کیا جاتا ہے. اشیاء کی کاپیاں کبھی خود بخود نہیں بنتی ہیں۔ اگر آپ کسی بلی کو کسی طریقہ پر اعتراض کرتے ہیں اور اس کی عمر کو تبدیل کرتے ہیں تو آپ اس کی عمر بدل دیں گے۔ لیکن اقدار اور/یا کالنگ کے طریقوں کو تفویض کرتے وقت حوالہ متغیر کو کاپی کیا جاتا ہے! آئیے یہاں اس بات کو دہراتے ہیں جو ہم نے پرائمیٹوز کو پاس کرنے کے بارے میں کہا تھا: "جب ہم changeInt () طریقہ کو کہتے ہیں اور int متغیر کو پاس کرتے ہیں x (=15) ، تو طریقہ خود x متغیر حاصل نہیں کرتا ہے، بلکہ اس کی ایک کاپی حاصل کرتا ہے۔ لہذا، کاپی میں کی گئی کوئی بھی تبدیلی ہمارے اصل x متغیر کو کسی بھی طرح متاثر نہیں کرتی ہے۔" حوالہ جات کاپی کرتے وقت، سب کچھ بالکل اسی طرح کام کرتا ہے! آپ بلی اعتراض کو طریقہ پر منتقل کرتے ہیں۔ اگر آپ خود بلی کے ساتھ کچھ کرتے ہیں (یعنی میموری میں موجود آبجیکٹ کے ساتھ)، تو آپ کی تمام تبدیلیاں کامیابی کے ساتھ لاگو ہو جائیں گی، کیونکہ ہمارے پاس صرف ایک چیز تھی اور اب بھی صرف ایک چیز ہے۔ لیکن، اگر آپ طریقہ کار کے اندر ایک نیا آبجیکٹ بناتے ہیں اور اسے ایک دلیل کے طور پر طریقہ کو پاس کیے گئے حوالہ متغیر کو تفویض کرتے ہیں، تو آپ صرف نئے آبجیکٹ کو حوالہ متغیر کی ایک کاپی کے لیے تفویض کر رہے ہوں گے۔ اس لمحے سے، ہمارے پاس دو آبجیکٹ اور دو حوالہ متغیر ہوں گے۔ یہی ہے! یہ اتنا آسان نہیں تھا۔ آپ کو کئی بار سبق بھی پڑھنا پڑا ہوگا۔ لیکن، اہم بات یہ ہے کہ آپ نے اس انتہائی اہم موضوع پر عبور حاصل کر لیا ہے۔ آپ اب بھی ایک سے زیادہ بار بحث کریں گے کہ جاوا میں دلائل کیسے پاس کیے جاتے ہیں (یہاں تک کہ تجربہ کار ڈویلپرز کے درمیان بھی)۔ لیکن، اب آپ جانتے ہیں کہ یہ کیسے کام کرتا ہے۔ اسے جاری رکھیں! :) جو کچھ آپ نے سیکھا ہے اس کو تقویت دینے کے لیے، ہمارا مشورہ ہے کہ آپ ہمارے جاوا کورس سے ایک ویڈیو سبق دیکھیں