অন্যরা কি বলছে, রিটার্ন টাইপ দ্বারা ওভারলোডিং বিপক্ষে হয় সম্ভব এবং করা হয় কিছু আধুনিক ভাষা দ্বারা সম্পন্ন। স্বাভাবিক আপত্তিটি কোডের মতো
int func();
string func();
int main() { func(); }
কোনটি func()
বলা হচ্ছে তা আপনি বলতে পারবেন না । এটি কয়েকটি উপায়ে সমাধান করা যেতে পারে:
- এমন পরিস্থিতিতে কোন ফাংশনটি ডাকা হবে তা নির্ধারণ করার জন্য একটি অনুমানযোগ্য পদ্ধতি রয়েছে।
- যখনই এ জাতীয় পরিস্থিতি দেখা দেয় এটি একটি সংকলন-সময় ত্রুটি। যাইহোক, একটি বাক্য গঠন যে দুর্বোধ্য, যেমন করতে প্রোগ্রামার পারবেন আছে
int main() { (string)func(); }
।
- পার্শ্ব প্রতিক্রিয়া নেই। যদি আপনার কোনও পার্শ্ব প্রতিক্রিয়া না থাকে এবং আপনি কখনই কোনও ফাংশনের রিটার্ন মান ব্যবহার করেন না, তবে সংকলকটি প্রথম স্থানে ফাংশনটি কল করা কখনও এড়াতে পারে।
আমি নিয়মিত দুটি ভাষা ( আব ) রিটার্ন টাইপের মাধ্যমে ওভারলোড ব্যবহার করি: পার্ল এবং হাস্কেল । তারা কি করে তা আমাকে বর্ণনা করুন।
ইন পার্ল , তার মাঝে একটি মৌলিক পার্থক্য স্কালে এবং তালিকা প্রসঙ্গ (এবং অন্যদের, কিন্তু আমরা ভান করব দুই আছে)। পার্লের প্রতিটি অন্তর্নির্মিত ফাংশন যে প্রসঙ্গে বলা হয় তার উপর নির্ভর করে বিভিন্ন জিনিস করতে পারে । উদাহরণস্বরূপ, join
অপারেটর তালিকা প্রসঙ্গে তালিকাবদ্ধ করে (জিনিসটি যুক্ত হওয়ার সাথে সাথে) scalar
অপারেটর যখন স্কেলারের প্রসঙ্গটি জোর করে, তাই তুলনা করুন:
print join " ", localtime(); # printed "58 11 2 14 0 109 3 13 0" for me right now
print scalar localtime(); # printed "Wed Jan 14 02:12:44 2009" for me right now.
পার্লের প্রতিটি অপারেটর স্কেলারের প্রসঙ্গে এবং তালিকার প্রসঙ্গে কিছু করে এবং চিত্রিত হিসাবে সেগুলি আলাদা হতে পারে। (এটি কেবল এলোমেলো অপারেটরগুলির মতো নয় localtime
you @a
আপনি যদি তালিকার প্রসঙ্গে কোনও অ্যারে ব্যবহার করেন তবে এটি অ্যারেটি ফেরত দেয়, যখন স্কেলারের প্রেক্ষাপটে এটি উপাদানগুলির সংখ্যা প্রদান করে So সুতরাং উদাহরণস্বরূপ print @a
উপাদানগুলি print 0+@a
মুদ্রণের সময় , আকারটি প্রিন্ট করে। ) তদ্ব্যতীত, প্রতিটি অপারেটর একটি প্রসঙ্গ জোর করতে পারে , উদাহরণস্বরূপ +
সংযোজনকারী প্রসঙ্গে প্রযোজ্য বাহিনীকে বাধ্য করে। man perlfunc
নথি প্রতিটি এন্ট্রি । উদাহরণস্বরূপ, এখানে প্রবেশের অংশটি এখানে glob EXPR
:
তালিকার প্রসঙ্গে, EXPR
স্ট্যান্ডার্ড ইউনিক্স শেলের মতো ফাইলের নামের বিস্তারের একটি (সম্ভবত শূন্য) তালিকা প্রদান করে /bin/csh
। স্কেলারের প্রসঙ্গে, গ্লোব এ জাতীয় ফাইলের বিস্তারের মাধ্যমে পুনরাবৃত্তি করে, তালিকাটি শেষ হয়ে গেলে অপরিবর্তিত হয়।
এখন, তালিকা এবং স্কেলারের প্রসঙ্গে কিসের সম্পর্ক? ভাল, man perlfunc
বলেছেন
নিম্নলিখিত গুরুত্বপূর্ণ নিয়মটি মনে রাখবেন: এমন কোনও নিয়ম নেই যা মাপকাঠির প্রসঙ্গে তার আচরণের সাথে তালিকার পরিপ্রেক্ষিতে কোনও অভিব্যক্তির আচরণের সাথে সম্পর্কিত বা বিপরীতভাবে tes এটি দুটি সম্পূর্ণ ভিন্ন জিনিস করতে পারে। প্রতিটি অপারেটর এবং ফাংশন স্থিতিশীল প্রসঙ্গে ফিরে আসার জন্য কোন ধরণের মানটি সবচেয়ে উপযুক্ত তা স্থির করে। কিছু অপারেটর তালিকার দৈর্ঘ্য ফিরিয়ে দেয় যা তালিকা প্রসঙ্গে ফিরে আসত। কিছু অপারেটর তালিকার প্রথম মানটি ফেরত দেয়। কিছু অপারেটর তালিকার শেষ মানটি ফেরত দেয়। কিছু অপারেটর সফল অপারেশনগুলির একটি গণনা ফিরিয়ে দেয়। সাধারণভাবে, আপনি যা চান তা তারা করেন, যদি না আপনি ধারাবাহিকতা চান।
সুতরাং এটি একটি একক ক্রিয়াকলাপ করার কোনও সাধারণ বিষয় নয় এবং তারপরে আপনি শেষে সাধারণ রূপান্তর করেন। আসলে, আমি localtime
সেই কারণটির জন্য উদাহরণটি বেছে নিয়েছি ।
এটি কেবল বিল্ট-ইনগুলিই নয় যেগুলির এই আচরণ রয়েছে। যে কোনও ব্যবহারকারী এই জাতীয় ফাংশনটি ব্যবহার করে সংজ্ঞায়িত করতে পারেন wantarray
যা আপনাকে তালিকা, স্কেলার এবং শূন্য প্রসঙ্গের মধ্যে পার্থক্য করতে দেয়। সুতরাং, উদাহরণস্বরূপ, যদি আপনি অকার্যকর প্রসঙ্গে ডাকা হয় তবে আপনি কিছুই করার সিদ্ধান্ত নিতে পারেন।
এখন, আপনি অভিযোগ করতে পারেন যে এটি রিটার্ন ভ্যালু দ্বারা সত্য ওভারলোডিং নয় কারণ আপনার কেবল একটি ফাংশন রয়েছে, যা বলা হয় সেই প্রসঙ্গে বলা হয় এবং সেই তথ্যটিতে কাজ করে। যাইহোক, এটি স্পষ্টতই সমতুল্য (এবং পার্ল কীভাবে আক্ষরিক অর্থে সাধারণ ওভারলোডিংকে অনুমতি দেয় না তার অনুরূপ, তবে একটি ফাংশন কেবল তার যুক্তিগুলি পরীক্ষা করতে পারে)। তদুপরি, এটি এই প্রতিক্রিয়ার শুরুতে উল্লিখিত দ্ব্যর্থক পরিস্থিতি সুন্দরভাবে সমাধান করে। পার্ল অভিযোগ করেন না যে এটি কোন পদ্ধতিটি কল করতে জানে না; এটা ঠিক এটি কল। এটিকে যা করতে হবে তা হ'ল ফাংশনটি কী প্রসঙ্গে ডাকা হয়েছিল, যা সর্বদা সম্ভব:
sub func {
if( not defined wantarray ) {
print "void\n";
} elsif( wantarray ) {
print "list\n";
} else {
print "scalar\n";
}
}
func(); # prints "void"
() = func(); # prints "list"
0+func(); # prints "scalar"
(দ্রষ্টব্য: আমি কখনও কখনও পার্ল অপারেটর বলতে পারি যখন আমি ফাংশন বলতে চাইছি This এটি এই আলোচনার পক্ষে গুরুত্বপূর্ণ নয়))
পার্শ্ব প্রতিক্রিয়া না হওয়ার জন্য হাস্কেল অন্য পদ্ধতি অবলম্বন করে। এটিতে একটি শক্তিশালী টাইপ সিস্টেম রয়েছে এবং তাই আপনি নীচের মতো কোড লিখতে পারেন:
main = do n <- readLn
print (sqrt n) -- note that this is aligned below the n, if you care to run this
এই কোডটি স্ট্যান্ডার্ড ইনপুট থেকে ভাসমান পয়েন্ট সংখ্যাটি পড়ে এবং এর বর্গমূলকে মুদ্রণ করে। তবে এতে অবাক হওয়ার কী আছে? ওয়েল, ধরণ readLn
হয় readLn :: Read a => IO a
। এর অর্থ কী তা হ'ল যে কোনও প্রকারের জন্য Read
(আনুষ্ঠানিকভাবে, প্রতিটি ধরণের যা Read
টাইপ শ্রেণীর একটি উদাহরণ ), readLn
এটি পড়তে পারে। হাস্কেল কীভাবে জানল যে আমি একটি ভাসমান পয়েন্ট নম্বর পড়তে চাইছি? ওয়েল, ধরণ sqrt
হয় sqrt :: Floating a => a -> a
, যা মূলত মানে যে sqrt
শুধুমাত্র ভাসমান ইনপুট হিসাবে পয়েন্ট সংখ্যা গ্রহণ করতে পারে, এবং তাই Haskell, অনুমিত আমি যা চেয়েছিলাম।
হাসেল যখন আমি যা চাই তা অনুমান করতে না পারলে কী ঘটে? ঠিক আছে, কয়েকটি সম্ভাবনা আছে। আমি যদি রিটার্ন মানটি ব্যবহার না করি তবে হাস্কেল কেবল প্রথম স্থানে ফাংশনটি কল করবে না। যাইহোক, যদি আমি না ফেরত মান ব্যবহার করেন, তারপর Haskell, অভিযোগ করবে এটা টাইপ অনুমান পারে না:
main = do n <- readLn
print n
-- this program results in a compile-time error "Unresolved top-level overloading"
আমি যে প্রকারটি চাই তা উল্লেখ করে আমি অস্পষ্টতাকে সমাধান করতে পারি:
main = do n <- readLn
print (n::Int)
-- this compiles (and does what I want)
যাইহোক, এই পুরো আলোচনার অর্থ কী তা হ'ল রিটার্ন ভ্যালু দ্বারা ওভারলোডিং সম্ভব এবং এটি সম্পন্ন হয়েছে, যা আপনার প্রশ্নের অংশের উত্তর দেয়।
আপনার প্রশ্নের অন্য অংশটি কেন আরও বেশি ভাষা তা করে না। আমি অন্যদের উত্তর দিতে হবে। তবে কয়েকটি মন্তব্য: মূল কারণটি হ'ল যুক্তির ধরণের মাধ্যমে ওভারলোডিংয়ের চেয়ে বিভ্রান্তির সুযোগটি সত্যই এখানে বেশি। আপনি স্বতন্ত্র ভাষা থেকে যুক্তিগুলিও দেখতে পারেন:
অ্যাডা : "এটি উপস্থিত হতে পারে যে সহজতম ওভারলোড রেজোলিউশন নিয়মটি হ'ল ওভারলোডেড রেফারেন্সটি সমাধান করার জন্য - যতটা সম্ভব প্রাসঙ্গিক থেকে সমস্ত তথ্য - ব্যবহার করা This এই নিয়মটি সহজ হতে পারে তবে এটি সহায়ক নয় It এটি মানব পাঠকের প্রয়োজন লেখার বড় আকারের টুকরো স্ক্যান করতে, এবং উপরের স্বেচ্ছাসেবী জটিল সূচনাগুলি (যেমন (ছ)) তৈরি করা আমাদের বিশ্বাস, আমরা বিশ্বাস করি যে একটি ভাল নিয়ম এমনটি যা স্পষ্ট করে তোলে যা একজন পাঠক বা সংকলককে অবশ্যই সম্পাদন করতে হবে, এবং এটি এই কাজটি করে তোলে মানুষের পাঠকের পক্ষে যতটা সম্ভব প্রাকৃতিক "
সি ++ (বার্জন স্ট্রোস্ট্রপের "দ্য সি ++ প্রোগ্রামিং ল্যাঙ্গুয়েজ" এর 7 অনুচ্ছেদ): "ওভারলোড রেজোলিউশনে রিটার্নের ধরণগুলি বিবেচনা করা হয় না The কারণটি কোনও পৃথক অপারেটর বা ফাংশন কল প্রসঙ্গে স্বাধীন রাখার জন্য রেজোলিউশন রাখে Consider বিবেচনা করুন:
float sqrt(float);
double sqrt(double);
void f(double da, float fla)
{
float fl = sqrt(da); // call sqrt(double)
double d = sqrt(da); // call sqrt(double)
fl = sqrt(fla); // call sqrt(float)
d = sqrt(fla); // call sqrt(float)
}
যদি রিটার্নের ধরনটি বিবেচনায় নেওয়া হয়, তবে sqrt()
বিচ্ছিন্নতার ডাকটি দেখার জন্য এবং কোন ফাংশনটি ডাকা হয়েছিল তা নির্ধারণ করা আর সম্ভব হবে না "" (দ্রষ্টব্য, তুলনা করার জন্য, হাসকেলে কোনও অন্তর্নিহিত রূপান্তর নেই ))
জাভা ( জাভা ভাষার স্পেসিফিকেশন 9.4.1 ): "উত্তরাধিকারসূত্রে প্রাপ্ত পদ্ধতিগুলির মধ্যে একটি অবশ্যই অন্য উত্তরাধিকারসূত্রে প্রাপ্ত পদ্ধতির জন্য রিটার্ন-টাইপ-সাবস্টিটিউটেবল হতে হবে, অন্যথায় একটি সংকলন-সময় ত্রুটি ঘটে" " (হ্যাঁ, আমি জানি এটি একটি যৌক্তিকতা দেয় না I'm আমি নিশ্চিত যে "জাভা প্রোগ্রামিং ল্যাঙ্গুয়েজ") গোসলিংয়ের পক্ষ থেকে যুক্তিটি দেওয়া হয়েছিল someone সম্ভবত কারও একটি অনুলিপি আছে? আমি বাজি ধরেছি এটি মূলত "সর্বনিম্ন আশ্চর্যতার মূলনীতি"। ) তবে জাভা সম্পর্কে মজাদার ঘটনা: জেভিএম রিটার্ন ভ্যালু দিয়ে ওভারলোডিংয়ের অনুমতি দেয় ! উদাহরণস্বরূপ, স্কালায় এটি ব্যবহার করা হয় এবং জাভা দিয়ে সরাসরি ইন্টার্নাল দিয়ে ঘুরে বেড়ানো যায়।
পুনশ্চ. চূড়ান্ত নোট হিসাবে, আসলে একটি কৌশল দিয়ে সি ++ এ রিটার্ন মান দ্বারা ওভারলোড করা সম্ভব। সাক্ষী:
struct func {
operator string() { return "1";}
operator int() { return 2; }
};
int main( ) {
int x = func(); // calls int version
string y = func(); // calls string version
double d = func(); // calls int version
cout << func() << endl; // calls int version
func(); // calls neither
}