সব গাছ ছাড়িয়ে
উঁকি মারে আকাশে।
মনে সাধ, কালো মেঘ ফুঁড়ে যায়
একেবারে উড়ে যায়;
কোথা পাবে পাখা সে?
৮ অবজেক্ট এবং হাতি
হুকুশ পাকুশ, তুমি কি তোমার হাতদুটো দিয়ে তোমার চোখ বন্ধ করবা? তারপর চলো আমরা একটা হাতির কথা ভাবি।হাতির কি কি আছে? একটা শুড় আছে, চারটা পা আছে, দুইটা চোখ আছে, একটা লম্বা লেজ আছে - সেটা দিয়ে হাতি মাছি তাড়ায়, আর পেন্ডুলামের মত দোলাতে থাকে কোন কাজ না পেলে। আর হাতির গায়ের রংটা না একদম মাটির মতো।
হাতি কি কি করে? হাতি শুড় উঁচিয়ে বৃংহতি টাইপের ডাক দিতে পারে। হাতি পুটুশ পাটুশ করে কোমড় দুলিয়ে হাঁটতে জানে। হাতি আবার রাজাদেরকে পিঠে নিয়ে হাঁটতেও খুব পছন্দ করে।
তো দেখো, আমরা পুরো আস্ত একটা হাতির বর্ণনা দিয়ে ফেললাম, হাতিটার কি কি আছে আর সে কি কি পারে সেটা দিয়ে। প্রোগ্রামিং এ মাঝে মাঝে আমাদের হাতি টাইপের কিছু প্রোগ্রাম লেখা লাগে - যেটা কিছু ডাটা রাখতে পারবে (হাতির লেজ, পা, চোখ যেমন তেমন) আর কিছু কাজ করতে পারবে (হাতি যেমন রাজাকে পিঠে নিয়ে হাঁটতে পারে তেমন)। তো আমরা যদি একবার হাতি প্রোগ্রামটাকে লিখে ফেলি - আমাদের আর কখনো ওটাকে নতুন করে লিখতে হবে না। যখনই হাতির দরকার হবে, আমরা হাতি প্রোগ্রামটাকে নিয়ে আসবো।
তো মজা হচ্ছে কি, আমরা এখানে হাতি প্রোগ্রামটাকে একটা জিনিস হিসেব ভাবছি। তাই না? যেমন টেবিল একটা জিনিস, হাতি একটা জিনিস, মানুষ একটা জিনিস। তো এভাবে প্রোগ্রামিং করাটাকে বলে object oriented programming - যেখানে সব প্রোগ্রামরা হচ্ছে একেকটা object - চেয়ার টেবিল কিংবা হাতির মতো। প্রোগ্রামিং এ একটা অবজেক্ট এর কাছে কিছু ডাটা থাকে (ভ্যারিয়েবল আরকি), আর কিছু ফাংশন থাকে। ফাংশনগুলো হচ্ছে অনেকটা কাজ করার মতো - যেগুলো ওই অবজেক্টটা করতে পারে।
এখন প্রশ্ন হচ্ছে আমরা যদি এখন আমাদের হাতিটার পিঠে দুটা ডানা গুঁজে দেই, হাতিটা কি আমাদের রেখে উড়ে চলে যাবে?
৮.১ হুকুশ পাকুশের প্রথম অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং
সেটা বোঝার আগে এই কনসেপ্টটা বোঝার জন্য আমরা একটা সহজ ক্যালকুলেটর অবজেক্ট বানাবো। অবজেক্টের আরেকটা নাম হচ্ছে ক্লাস। আমরা এখন একটা ক্যালকুলেটর ক্লাস নিবো, যার দুইটা ভ্যারিয়েবল থাকবে। আমি চাইলে ভ্যারিয়েবলগুলো পাল্টাতে পারবো, আর ক্যালকুলেটরকে জিজ্ঞেস করতে পারবো, 'ওহে ক্যালকুলেটর, তোমার ভ্যারিয়েবলদের যোগফল কত শুনি?'।
ক্লাসের ভেতর ফাংশন লেখার সময় সবসময় ক্লাসটাকে বলে দিতে হয় সে কে। তুমি কি ফিফটি ফার্স্ট ডেট মুভিটা দেখেছো? ওখানে টেন সেকেন্ড টম ছিলো না, যে দশ সেকেন্ড পর পর ভুলে যেতো সে কে? সেরকম যাতে না হয়, সেজন্য পাইথনে আমরা সব সময় self প্যারামিটারটা পাস করতে থাকি। যাতে কখনো ক্লাসটা তার নিজেকে ভুলে না যায়।
ক্লাসটার পরের অংশটাতে আমরা c বলে একটা ভ্যারিয়েবল বানিয়েছি - আর বলে দিয়েছি যে c হচ্ছে আসলে একটা ক্যালকুলেটর টাইপের অবজেক্ট। পরের অংশটুকু সহজ। তুমি যদি c এর কোন একটা জিনিস নাড়াচাড়া করতে চাও - তোমাকে শুধু c এর পরে একটা ডট দিয়ে ভ্যারিয়েবলের নাম বা ফাংশনের নামটা লিখতে হবে।
তুমি জিজ্ঞাসা করতেই পারো, যে কেন আমরা এভাবে লিখছি? এই জিনিস তো ক্লাস না ব্যবহার করেও করা যেতো। ব্যাপারটা অনেকটা এরকম, ধরো রাজার দুইটা হাতি লাগবে একসাথে - আজকে রাজপূত্রকে নিয়ে সে হাতিতে চড়ে পাহাড়ে হাঁটতে যাবে। তখন আমার দুইটা হাতির অস্তিত্ব লাগবে। দুইটা হাতিই হাতি - কিন্তু তারপরও ওরা দুইটা আলাদা হাতি। হাতির আলাদা আলাদা অস্তিত্বকে প্রোগ্রামিং এর ভাষায় বলা হয় আলাদা দুইটা instance।
অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং আসলে একটা হাতি টাইপের বড় সড় টাইপের জিনিস। অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং নিয়ে একটা মোটাসোটা বই লিখে ফেলা যায়, বাচ্চা কাচ্চাদের ভয় পাইয়ে দেয়া যায়, একটা ইউনিভার্সিটি কোর্স নিয়ে ফেলা যায়, অনেকগুলো লেকচারও দিয়ে ফেলা যায়। কিন্তু আমি সেগুলোর কিছুই করবো না, কারণ আমি শুধু চাচ্ছি তোমার সাথে ওদের পরিচয় করিয়ে দিতে। তোমরা পরিচিত হয়ে বন্ধু হবে নাকি একজন আরেকজনকে ভয় দেখাবে সেটা তোমাদের ব্যাপার। বুঝছো হুকুশ পাকুশ?
৮.১ ইনহেরিটেন্স
ধরো আমি একটা হাতি চাই, যেই হাতিটার ডানা আছে। ও আমাকে নিয়ে উড়তে পারবে মেঘের ওপর, তারাদের কাছাকাছি। এখন যদি একটা হাতি অলরেডি বানানো থাকে, আমার কিন্তু হাতিটাকে আগাগোড়া বানাতে হবে না। শুধু আগে বানানো হাতিটাকে নিয়ে ওর দুপাশে দুটো ডানা জুড়ে দিতে হবে। তাই না?
এই কন্সেপ্টটাকে বলে ইনহেরিটেন্স (inheritence)। আমরা একটা প্রোগ্রাম নেই, তারপর প্রোগ্রামটার একটা বাচ্চা বানাই, যেই প্রোগ্রামটা সবকিছুই পারবে ওর বাবা প্রোগ্রামটা যা কিছু পারতো, কিন্তু তাকে আমি আরো অনেককিছু শেখাবো যেটা ওর বাবা প্রোগ্রামটা জানতো না। প্রোগ্রামারের লাভটা হচ্ছে, তাকে পুরো প্রোগ্রামটা কষ্ট করে শুরু থেকে লিখতে হচ্ছে না - শুধু নতুন অংশটুকু লিখতে হচ্ছে।
যেমন ধরো, আমাদের আগের ক্যালকুলেটরটা গুণ করতে জানতো না। কেমন হয় যদি আমরা আরেকটা বাচ্চা বানাই ওই ক্যালকুলেটরটার, যেটা গুণ করতে জানবে? তখন প্রোগ্রামটা হবে এরকম -
দেখো, তোমাকে যে সব সময় শুধু নতুন কিছু যোগ করতে হবে তা কিন্তু না। তুমি কোন অংশ নিয়ে পাল্টেও ফেলতে পারো। যেমন ধরো, বাবা হাতিটা সিগারেট খেতো, সেজন্য বাবু হাতি, যে কিনা উড়তে জানে, সেও কি সিগারেট খাবে? কখখনো না! আমরা বাবু হাতিকে লেখার সময় ওই অংশটুকু পাল্টে ফেলতেই পারি।
খেয়াল করো NewCalculator কে ডিক্লেয়ার করার সময় বলে নিতে হচ্ছে ওর বাবার নাম কি। এটা অনেকটা মানুষের নামের শেষ অংশের মতো, last name যেটাকে বলে। যেমন সত্যজিৎ (রায়) - রায় নামটা সে পেয়েছে ওর বাবার কাছ থেকে - ওরকম।
তোমার ঘরে বসত করে কয় জনা - মন জানো না
তোমার ঘরে বসত করে কয় জনা?
একজনে ছবি আঁকে একমনে - ও হো ও মন
আরেকজন বসে বসে রঙ মাখে - ও হো ও মন
ওহো আবার - সেই ছবিখান নষ্ট করে কোন জনা
কোন জনা?
একজন সুর তোলে এক তারে, ও হো ও মন
আরেকজন মন্দিরাতে তাল তোলো, ও হো ও মন
ওহ আবার বেসুরা সুর ধরে দেখো কোন জনা
কোন জনা?
তোমার ঘরে বসত করে কয় জনা - মন জানো না!
৮.২ পলিমর্ফিজম
দেখো হুকুশ পাকুশ, তোমার চারপাশে কত্ত মানুষ। সবাই একইরকম - সবার দুইটা করে হাত, দুইটা করে পা, একটা করে নাক, দুইটা করে চোখ। কিন্তু তারপরও সবাই কত্ত আলাদা না ভাবো? কেও হাসিখুশি, কেউ মুখ গোমড়া। কেউ কিছুতেই মন খারাপ করে না, আর কারো কখনোই মন ভালো হয় না। কেউ কখনোই আশা ছেড়ে দেয় না, আর কেউ কেউ স্বপ্ন দেখতেই জানে না। কিন্তু সবার মূল আকৃতি একই রকম। সবার হাত কাটলে লাল রক্ত বের হয়, মন খারাপ হলে চোখ ফেটে পানি পড়ে।
মাঝে মাঝে আমাদের কিছু প্রোগ্রাম লিখতে হয়, যাদের সবার আকৃতি একই রকম - কিন্তু মানুষের মত তারা সবাই আলাদা আলাদা। সেরকম ক্ষেত্রে আমরা একটা সাধারণ প্রোগ্রাম লিখে নেই, যেটা ওদের মূল আকৃতিটুকু ধরে রাখবে। তারপর বাকিদেরকে লিখি সেই মূল আকৃতির উপর ভিত্তি করে। এই কনসেপ্টটাকে বলে পলিমরফিজম (polymorphism)।
একটা ছোট্ট সহজ উদাহরণ দেই। ধরো আমার বাসায় আমি একটা ছোট্ট চিড়িয়াখানা বানাবো হুকুশ পাকুশের জন্য। আমার একটা বাঘ থাকবে, আর বাঘটা বলবে "হালুম!"। আর থাকবে বিড়াল, ইঁদুর আর একটা ছোট্ট বাচ্চা কুকুর। বিড়ালটা বলবে "মিয়াও!", ইঁদুরটা বলবে "কিঁচ কিঁচ" আর বাচ্চা কুকুরটা বলবে, "হুফ! হুফ!"। আর ওদের সবার একটা করে নাম থাকবে। তো দেখো - ওদের মূল আকৃতিটা হচ্ছে - ওদের প্রত্যেকের নাম আছে আর সবার একটা ডাকও আছে।
তাহলে আমাদের প্রোগ্রামটা হবে এরকম
এখানে __init__ ফাংশনটা হচ্ছে আমাদের আগে একটা set ফাংশন ছিলো না? ঠিক ওরকম। পার্থক্য হচ্ছে, এভাবে লিখলে, ইনস্ট্যান্স তৈরী করার সময়ই সেট করে নেয়া যায়। যেমন দেখো আমরা এখানে অবজেক্টটা তৈরী করার সময়ই ব্র্যাকেটের ভিতরেই নামটা বলে দিচ্ছি।
Pet হচ্ছে আমাদের মূল ক্লাস, যেটার হচ্ছে বাকি সব ক্লাসগুলোর মূল আকৃতি। আমরা এই ধরণের ক্লাসকে বলি অ্যাবস্ট্রাক্ট ক্লাস। বাকি সব ক্লাসগুলোতে আমরা করছি Pet কিভাবে কথা বলবে, সেটা ঠিক করে দিচ্ছি। এইটাই হচ্ছে পলিমর্ফিজম।
পলিমরফিজম কোডকে তুলনামূলকভাবে সহজ আর গোছানো করে দেয়। যখন প্রোগ্রামাররা একটা বড় সিস্টেম তৈরী করে, তখন ডিজাইনটা খুব গুরুত্বপূর্ণ হয়ে যায়। ডিজাইন যদি হিজিবিজি হিজিবিজি হয় তখন কোড করতে, প্রোগ্রামটাকে ঠিকঠাক মতো রান করতে খবর হয়ে যায়। আর যখন ডিজাইন খুব সহজ, সুন্দর আর গুটুশগাটুশ টাইপের হয় তখন কোডগুলোও সহজ আর সুন্দর হয় - তখন কোডটাকে গড়গড় করে কবিতার মতো করে পড়ে ফেলা যায়। আর মুগ্ধ হয়ে তাকিয়ে থাকা যায় অনেক অনেক সময় ধরে।
৮.৩ পাইথন মডিউলস
মনে আছে হুকুশ পাকুশ, আমরা লাইব্রেরী ফাংশন দেখেছিলাম আগের চ্যাপ্টারে? পাইথনের লাইব্রেরীতে একইভাবে অনেকগুলো ক্লাস টাইপের প্রোগ্রাম লেখা আছে। সেই প্রোগ্রামগুলোকে বলে মডিউল। একেকটা মডিউলে অনেকগুলো করে ফাংশন থাকে, যেগুলোকে আমরা ক্লাসের ফাংশন নিয়ে যেভাবে কাজ করি, সেভাবে কাজ করতে পারি। আমরা যদি সেই মডিউলগুলোকে ব্যবহার করতে চাই, আমাদের সেগুলো import করতে হবে।
যেমন ধরো তোমার যদি ফ্যাক্টোরিয়াল বের করার জন্য ফাংশন লিখতে হয়, সেটা ইতিমধ্যে পাইথনের লাইব্রেরীতে লেখা আছে math নামের একটা মডিউলে। তাই আমরা নতুন করে আর ওটাকে না লিখে করবো কি, লাইব্রেরী থেকে ওই মডিউলকে import করে এনে সেটাকে ব্যবহার করে ফেলবো!
পাইথনের পুরো লাইব্রেরিটার খুটিনাটি তুমি পাবে এই লিংকটাতে। যেমন তুমি যদি সেখান থেকে math মডিউলটাকে ক্লিক করো, তাহলে তুমি এইটা দেখতে পাবে, যেই মডিউলটা আমরা এই মাত্র ব্যবহার করলাম।