মেথড ওভারলোডিং- ওভাররাইডিং - Method overloading - overriding

আমার এই লেখাটা বেশ কিছুদিন আগের। তখন আমি আমার প্রফেসর ড. ক্রিস্টফ চালনারের সফটওয়্যার ইঞ্জিনিয়ারিং কোর্সের টিচিং এসিস্টান্ট বা টি-এ ছিলাম। 

--------------------------------------------------------------------------------------------------------------------------

আমি এই সেমিস্টার-এ যেই কোর্সের টি-এ. তাতে একটা কুইজের প্রশ্ন ছিল অনেকটা এই রকম :


public class C {
public int foo (C p) { return 1;}
public int foo (E p) { return 2;}
}


public class D extends C {
public int foo (C p) { return 3;}
public int foo (D p) { return 4;}
}


public class E extends D {
public int foo (E p) { return 5;}
}


Write down the values after the ‘==’ symbol that will get returned after the sequence of statements as below:


C d = new D();
C e = new E();
D f  = new E();


e.foo(d) ==
d.foo(e) ==
d.foo(f)  ==
f.foo(e)  ==
f.foo(f)   ==


মেথড ‘ ওভারলোডিং -‘ওভাররাইডিং’ -এর প্রশ্ন। আমার বরাবরই এই দুইটা বিষয়ে গোলমাল লাগে। কোনটা যে কি মনে থাকে না। কুইজের খাতা দেখতে গিয়ে এক ছাত্রের উত্তর দেখেই পুরনো ভুল টা আবার শুধরালাম।


শুরুতেই বলে নেই (disclaimer): এটা সম্পূর্ন আমার নিজের বুঝে লেখা। পুরোটাই ভুল হতে পারে। তাই নিজ দায়িত্বে পড়তে হবে :-)

মেথড ওভারলোডিং - ওভাররাইডিং -এর উপর বেশ ভালো একটা আর্টিকেল আছে এই লিঙ্কে। আর্টিকেল টাতে ভ্যারিয়েবল শ্যাডোইং (variable shadowing) নিয়েও আলোচনা আছে।


উত্তর:
e.foo(d) == 3
d.foo(e) == 3
d.foo(f)  == 3
f.foo(e) ==  3
f.foo(f)   == 4

প্রথমত মনে রাখতে হবে: ওভারলোডিং হয় কম্পাইল-টাইমে, অর্থাৎ statically. আর ওভাররাইডিং হয় রান-টাইমে, অর্থাৎ dynamically. এই পার্থক্য মনে রাখতে আমি যেটা মনে রাখতে চেষ্টা করি তা হলো:

কোনো কিছু load করতে, যেমন ট্রাকে কিছু লোড করতে ট্রাকটাকে কিন্তু দাঁড় করিয়ে রাখতে হয়, অর্থাৎ static থাকা লাগে। আবার কোনো কিছু ride করতে, যেমন মোটরসাইকেল রাইড করতে হয় চালু অবস্থায়, অর্থাৎ dynamically.

এখন মেথড ওভারলোডিং হচ্ছে একই নামে ভিন্ন মেথড থাকলে তাদের প্যারামিটার  -এর সংখ্যা বা টাইপের উপর ভিত্তি করে মেথড কল হওয়া। এটা কম্পাইলার statically ঠিক করে। আর সেই হিসাবেই জাভাতে সোর্স কোড থেকে বাইটকোডে ইন্সট্রাকশন লিখে রাখে -- যেটা আর পরিবর্তন হয় না। অর্থাৎ, প্যারামিটারের টাইপ আর পরিবর্তন হবে না।

আর মেথড ওভাররাইডিং হচ্ছে প্রোগ্রাম চালু অবস্থায় (Runtime-এ) একটা ক্লাস (বা রেফারেন্স) ভ্যারিয়েবল যেই অবজেক্ট -কে রেফার করে তার মেথড কল হওয়া। এটা dynamic dispatch নামে পরিচিত। অর্থাৎ, রান টাইমে ঠিক হবে কোন অবজেক্টের মেথড কল হবে।

এখন আসা যাক কুইজের প্রশ্নে।

কম্পাইলার যেই ভাবে statically পুরো সোর্স কোডটা দেখবে  বা load করবে  তা হচ্ছে:

ক্লাস - প্যারামিটার টাইপ   == > রিটার্ন ভ্যালু
C.C == > 1
C.E == > 2
D.C == > 3
D.D == > 4
E.E == > 5

অর্থাৎ, উদাহরণ হিসাবে প্রথম দুইটা দেখি: C ক্লাসের একটা অবজেক্ট-এর foo মেথড যদি C প্যারামিটার দিয়ে কল করা হয় তবে তা 1 রিটার্ন করবে; আর যদি E প্যারামিটার দিয়ে করা হয় তাহলে 2 রিটার্ন করবে।

এখন ‘=>’ এই চিহ্ন কে static/compile time আর ‘#>’ চিহ্ন কে dynamic/ runtime হিসাবে ধরে কোডটা চিন্তা করলে এইরকম দাঁড়াবে : (মনে রাখতে হবে static code বা বাইটকোড অপরিবর্তিত থাকে )

C d = new D();
C e = new E();
D f  = new E();

e.foo(d) => C.C #> E.C (যেহেতু E ক্লাসের C প্যারামিটার দিয়ে কোনো মেথড নাই, তাই E’র সুপার ক্লাস কল হবে) #> D.C  == 3

d.foo(e) => C.C #> D.C == 3

d.foo(f)  => C.D => C.C (যেহেতু C ক্লাসের D প্যারামিটার দিয়ে কোনো মেথড নাই, তাই D -এর সুপার ক্লাস দিয়ে statically পরিবর্তন হবে) #> D.C == 3

f.foo(e) =>  D.C #> E.C (যেহেতু E ক্লাসের C প্যারামিটার দিয়ে কোনো মেথড নাই, তাই E’র সুপার ক্লাস কল হবে ) #> D.C  == 3

f.foo(f)   => D.D #> E.D (যেহেতু E ক্লাসের D প্যারামিটার দিয়ে কোনো মেথড নাই, তাই সুপার ক্লাস কল হবে ) #> D.D  == 4

এই হলো আমার নিজের ব্যাখ্যা। কোড টা আমি Java তে লিখে রান করে দেখেছি: উত্তর ঠিক আছে। আর এই ব্যাখ্যা বুঝতে আমাদের ব্যাচের মাইনুল ইসলাম বিপুল আমাকে সাহায্য করছে।

ধন্যবাদ।

--ইশতিয়াক

লাঞ্চ এন্ড লার্ন - জাভা ৯

লাঞ্চ এন্ড লার্ন - জাভা ৯ নভেম্বর ১০, শুক্রবার, ২০১৭ আমেরিকাতে আমার কাজের অভিজ্ঞতার মধ্যে এই একটা জিনিস আমার খুব প্রিয় - লাঞ্চ এন্ড লার্...