POLYMORPHISM এবং অবজেক্ট অরিয়েন্টেড সি++

সি++ এ বহুরূপতা কি, কেন এবং একটি ছোট Introduction to Virtual Function


আজ কথা বলবো বহুরূপতা নিয়ে। বহুরূপতা কি?

কখনো চিন্তা করেছেন কি আমরা মানুষরা একটি বহুরূপি প্রাণী? হ্যাঁ। ধরেন দেখি একটি পুরুষের ক্ষেত্রে। একটি পুরুষ একই সাথে একজন ছেলে, একজন বাবা, একজন ভাই, একজন স্বামী এবং একজন কর্মচারী। দেখেন কতগুলো রূপ। সবগুলোর চরিত্র কিন্তু আবার একেক গুলো থেকে আলাদা। একেক চরিত্রে তাকে একেক রকমের ব্যবহার করতে হয়। ঠিক একইভাবে একটি নারীও এরকম বহুরূপি। কখনও সে একজন মা, একজন মেয়ে, একজন বোন, একজন স্ত্রী অথবা একজন কর্মচারী। এটাকে বলে বহুরূপতা। এই বহুরূপতা আবার অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং এও আছে। তখন এই বহুরূপতাকে প্রোগ্রামিং এর ভাষায় বলে Polymorphism. Polymorphism শব্দটির অর্থ হচ্ছে একাধিক রূপ অথবা Form থাকা।

অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং এ এই Polymorphism অনেক গুরুত্বপূর্ণ একটি ফিচার। তাই সি++ OOP তেও এই Polymorphism বিশেষ ভূমিকা রাখে। Polymorphism তখনই হয় যেখানে অনেক গুলো class এর মধ্যে একটি Hierarchy থাকে এবং তারা Inheritance এর মাধ্যমে একে অপরের সাথে সম্পর্কিত থাকে।

সি++ Polymorphism এর কাজ হচ্ছে, যখন আমরা একটি মেম্বার ফাংশন কে কল করবো তখন সেই ফাংশনটি যে অবজেক্টের ধরনের উপর নির্ভর করে execute হবে সেই অবজেক্টের ফাংশন কে কল অথবা Invoke করা।

সি++ Polymorphism কে দুই ভাগে ভাগ করেছে —

১. কম্পাইল টাইম পলিমরফিসম(Compile time Polymorphism) এবং

২. রানটাইম পলিমরফিসম (Run time Polymorphism)


১. কম্পাইল টাইম পলিমরফিসম(Compile time Polymorphism) —

এই ধরনের Polymorphism Achieve করার জন্য আমাদের ফাংশন অভারলোডিং অথবা অপারেটর অভারলোডিং ব্যবহার করতে হয়।

# ফাংশন অভারলোডিং দিয়ে কম্পাইল টাইম পলিমরফিসম —

ফাংশন অভারলোড করার কিছু শর্ত আছে। সেগুলো হচ্ছে —

  • একাধিক ফাংশনের নামে এক হতে হবে,
  • কিন্তু এদের Parameters একে অপরের থেকে ভিন্ন হতে হবে
  • এদের Arguments Type ও ভিন্ন হতে হবে।

উপরের শর্ত গুলো Fulfill হলে তখন একটি ফাংশন অভারলোড হয়। ফাংশনকে তার Arguments এর সংখ্যায় পরিবর্তন অথবা ধরনের পরিবর্তন এনেও অভারলোড করা যায়।

চলুন এবার দেখি কীভাবে একটি অভারলোডেড ফাংশন পলিমরফিসমের অংশ হতে পারে।

আউটপুট দেখাবে —

Value of x is: 1 
Value of x is: 2.202
Value of x and y is: 3, 4

উপরের কোডে আমরা ভিন্ন ভিন্ন Parameters গ্রহণ করে অথচ একই ফাংশন এর তিন রকমের ভ্যালু রিসিভ করতে এবং সেগুলোকে আউটপুট হিসেবে দিতে দেখেছি। এটাই হচ্ছে ফাংশন অভারলোডিং দিয়ে কম্পাইল টাইম পলিমরফিসম।


#অপারেটর অভারলোডিং দিয়ে কম্পাইল টাইম পলিমরফিসম —

সি++ এ অপারেটর গুলোকেও অভারলোড করা যায়। যেমন আমরা যোগ (+) অপারেটর ব্যবহার করে আমরা দুইটা স্ট্রিং ক্লাশ কে যুক্ত করতে পারি। যোগ (+) চিহ্নের কাজ হচ্ছে দুই বা দুই এর অধিক বস্তু অথবা নাম্বারকে যুক্ত করা। তাই যখনই একটি (+) অপারেটর দুইটা ইন্টেজার ভ্যালুর মাঝখানে বসিয়ে দেয়া হয় তখন এই (+) অপারেটরের কারনে অই দুইটা ইন্টেজার ভ্যালু যুক্ত হয়ে যায়।

আউটপুট দেখাবে —

5 + i 7

উপরের কোডে (+) অপারেটর কে আমরা অভারলোড করেছি। এই (+) অপারেটরটির আসল কাজ হচ্ছে দুইটা নাম্বার (ইন্টেজার অথবা ফ্লোটিং পয়েন্ট নাম্বার) যোগ করা, কিন্তু উপরের কোডে আমরা এই (+) অপারেটর অভারলোড করে দুইটি কমপ্লেক্স অথবা ইমাজিনারি নাম্বার যোগ করেছি। এতে একই অপারেটরের দুই রকমের ব্যবহার দেখা গেছে। এটাকে অপারেটর অভারলোডিং বলে এবং এটাই অপারেটর অভারলোডিং দিয়ে কম্পাইল টাইম পলিমরফিসম।


২. রানটাইম পলিমরফিসম (Run time Polymorphism) —

এই টাইপের পলিমরফিসম শুধু ফাংশন অভাররাইডিং (Overriding)করে Achieve করা যায়। যখন একটি Derived অথবা Sub Class তার Base Class এর যেকোনো একটি মেম্বার ফাংশনকে সংজ্ঞায়িত করে তখন সেই Base Function টি override হয় এবং একে ফাংশন অভাররাইডিং বলে।

আউটপুট হবে —

Parent Print Function 
Child Print Function

ভার্চুয়াল ফাংশন (Virtual Function) —

Run time Polymorphism এর আরেকটি গুরুত্বপূর্ণ অংশ হচ্ছে ভার্চুয়াল ফাংশন। ভার্চুয়াল ফাংশন হচ্ছে একটি মেম্বার ফাংশন যেটাকে Base Class এর মধ্যে ডিক্ল্যায়ার করা হয় এবং Derived Class এ যেয়ে সেটা অভাররাইড হয়ে যায়। যখন কোনো Derived Class অবজেক্ট কে পয়েন্টার অথবা রেফারেন্স ব্যবহার করে Base Class এর সাথে রেফার করা হয়, তখন সেই অবজেক্টের জন্য Virtual Function কে কল করা যায় এবং সেটা সেই অবজেক্টকে Derived Class এর Function এর জন্য Execute করে দেয়।

ফাংশন কল করার জন্য রেফারেন্স অথবা পয়েন্টার এর টাইপ যেরকমই হোক না কেন, Virtual Function সবসময় এটা খেয়াল রাখে অবজেক্ট যেন সঠিক ফাংশনকে কল করছে। Virtual Function এ ব্যবহার করার জন্য ফাংশন গুলোকে Base Class এ Virtual কী-ওয়ার্ড ব্যবহার করা হয়।

এই Virtual Function এর কিছু রুলস আছে। সেগুলো হচ্ছে —

  • Virtual Function কে অবশ্যই Class এর Public Section এ Declare করতে হবে।
  • Virtual Function কখনোই Static অথবা অন্য Class এর Friend Function হতে পারবে না।
  • Run time Polymorphism ব্যবহার করার জন্য Virtual Function কে সবসময় Base Class থেকে রেফার করার জন্য Pointer অথবা Reference ব্যবহার করতে হবে।
  • Virtual Function এর প্রোটোটাইপ Base এবং Derived Class দুটোতেই এক হতে হবে।
  • Virtual Function কে সমসময় Base Class এ ডিক্ল্যায়ার করতে হবে। Derived Class এ অভাররাইড করা জরুরী না, সেক্ষেত্রে Base Class এর ফাংশন ব্যবহার হবে।
  • একটি Class এ Virtual Destructor থাকতে পারবে কিন্তু Virtual Constructor থাকতে পারবে না।

চলুন এবার আরেকটি প্রোগ্রাম দেখি —

আউটপুট হবে —

Derived Class

উপরের প্রোগ্রামটি Virtual Function ব্যবহার করে Run time Polymorphism এর একটি উদাহরণ। এই প্রোগ্রামের আসল জিনিষটা হচ্ছে Derived Class এ show() Function কে Base class থেকে pointer ব্যবহার করে কল করা হয়েছে। Virtual Function গুলোকে Pointed অথবা referred object type এর উপর ডিপেন্ড করে কল করা হয়।


Virtual Function কেন ব্যবহার করবো?

Virtual Function আমাদেরকে Base class pointer গুলোর একটি লিস্ট তৈরি করতে এলাউ করে এবং Derived Class অবজেক্ট কোন টাইপের তা জানা ছাড়াই Derived Class এর ম্যাথোডকে কল করতে পারে।

মনে করেন, একটি কোম্পানির কর্মচারী ম্যানেজমেন্টের জন্য একটি ম্যানেজমেন্ট সফটওয়্যার। সেই সফটওয়্যার এর একটি Employee নামক Base class আছে, যেখানে Base class এর ভিতর raiseSalary(), transfer(), promote() ইত্যাদি এরকম কিছু ফাংশন আছে। এখন কোম্পানিতে বিভিন্ন লেভেলের কর্মচারী থাকে, কেও ম্যানেজার, কেও ইঞ্জিনিয়ার। তো তাদের প্রত্যেকেরই Base class এর Virtual Function গুলোর ভিন্ন রকম নিজের মতোন করে implementation থাকতে পারে। কিন্তু আমরা আমাদের সফটওয়্যারে, শুধু একটি কর্মচারীদের লিস্ট পাস করবো এবং Virtual Function ব্যবহার করে যখন যেটা দরকার পড়বে সেই ফাংশনকে কল করবো, এক্ষেত্রে Virtual Function এর জানতে হবে না কোন কর্মচারী কোন ধরনের কাজ করছে। যেমন আমরা raiseSalary() ফাংশন ব্যবহার করে খুব সহজেই সবার বেতন বাড়িয়ে দিতে পারছি, এক্ষেত্রে আমাদের জানতে হচ্ছে না কর্মচারীটি কি ধরনের কাজ করে।

globalRaiseSalary() এর মতোন এরকম অনেক অপারেশনস থাকতে পারে যেটা অবজেক্ট টাইপ জানা ছাড়াই শুধু মাত্র কর্মচারী লিস্ট থেকেই সব কাজ করে ফেলতে পারবে।


অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং নিয়ে আমার আগের লিখা গুলো পড়তে পারবেন আমার ব্যক্তিগত ব্লগ এবং মিডিয়াম থেকে —

আজকে এই পর্যন্তই। ধন্যবাদ সাথে থাকার জন্য।

#হ্যাপি_প্রোগ্রামিং


আমার ব্যাক্তিগত ব্লগ —

বাংলা ভার্শন — https://with.dibakar.me/

ইংলিশ ভার্শন — https://with.dibakar.me/en/

আমাকে পাবেন —

ফেসবুকে — https://www.facebook.com/dipu.dibakar

মিডিয়ামে — https://medium.com/@iamdibakardipu

টুইটারে — https://twitter.com/iamdibakardipu

ইনস্টাগ্রামে — https://www.instagram.com/dibakardipu/

গিটহাবে — https://github.com/dibakarsutradhar

লিঙ্কড ইনে — https://linkedin.com/in/dibakardipu/