ক্লাস, অবজেক্ট এবং মেথড

ক্লাস, অবজেক্ট এবং মেথড

পাইথনে কোড করার আনন্দ এর সংক্ষিপ্ত, সহজবোধ্য ও রিড্যাবল ক্লাসগুলোর ভেতরে নিহিত; যেগুলো অল্পসংখ্যক স্পষ্ট কোডেই বহুসংখ্যক কাজ করতে পারে— এটি গাদা গাদা ফালতু কোডের সমাহার না, যা পাঠককে বিরক্তির শেষ সীমা অবধি নিয়ে যায়। - গুইডো ভ্যান রস্যিউম

বহু আগে, সেই কস্মিনকালে আমরা জেনেছি যে পাইথন একটি অবজেক্ট-অরিয়েন্টেড ল্যাঙ্গুয়েজ। এখানে আমরা সেই উপনামের শানে নুযুল জানব।

ক্লাস - খায় না পিন্দে?

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

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

এতটুকু যদি বুঝতে পারি আমরা, সেক্ষেত্রে নিশ্চয়ই বুঝতে পারছি যে প্রতিটা ‘ওয়ালটন উস্তা’তেই এই ফাংশনগুলা থাকবে। আর সবগুলো ফাংশন মিলিয়েই কিন্তু ‘ওয়ালটন উস্তা’ হবে। যদি কোন ফাংশন বাদ যায় বা এক্সট্রা কোন ফাংশন যোগ হয় তাহলে কিন্তু আর ‘ওয়ালটন উস্তা’ থাকবে না। তখন হয়ত নতুন নাম দেয়া হবে ‘ওয়ালটন চিচিঙ্গা’। যাহোক, এই যে কতগুলো ফাংশন নিয়ে আমাদের এই ‘ওয়ালটন উস্তা’ পয়দা হল, এখন ‘ওয়ালটন উস্তা’কে আমরা ক্লাস (class) বলতে পারি।

চলুন সবাই মিলে পাইথনিক উপায়ে ‘ওয়ালটন উস্তা’ ক্লাস তৈরি করি।

class WaltonUsta:
    """Our new car class"""

    def driving(self):
        run_the_car

    def music(self):
        run_the_music

    def fuel(self):
        load_the_fuel

    def horn(self):
        make_sound_pollution

আমরা এখানে WaltonUsta নামে একটা ক্লাস তৈরি করেছি আর তার ভিতর driving(), music(), fuel(), horn() চারটা ফাংশন তৈরি করেছি। এই নিয়ে হয়ে গেল আমাদের ক্লাস।

সেলফ (self)

আমি নিশ্চিত আমাদের অনেকেরই self নিয়ে ব্যাপক দুশ্চিন্তা হচ্ছে। এটা নিয়ে মাথা ঘামানোর আসলে তেমন কিছু নাই। কারণ:

  • self আসলে একটা কনভেনশনাল নাম। আমরা চাইলে এটাকে বদলে দিতে পারি।

  • self হল ক্লাস ইন্সট্যান্সের একটা রেফারেন্স। ইন্সট্যান্স ভ্যারিয়েবল ডিক্লেয়ার করার সময় self এর রেফারেন্স ব্যবহার করা হয়। ক্লাস ভ্যারিয়েবল আর ইন্সট্যান্স ভ্যারিয়েবলের ভিতর পার্থক্য হল ক্লাস ভ্যারিয়েবল ক্লাসের সব ইন্সট্যান্সের ভিতরেই শেয়ার্ড, অন্যদিকে ইন্সট্যান্স ভ্যারিয়েবল প্রতিটা ইন্সট্যান্সে ইউনিক।

অবজেক্ট (object) কী?

অবজেক্টের শাব্দিক অর্থ বস্তু। নামের মধ্যেই এর কাজের কথা বলা আছে। অবজেক্ট আসলে বস্তুবাদী মানে পার্থিব চিন্তার বিষয়। (পৃথিবীতে আমাদের সামনে দৃশ্যমান বস্তুই পার্থিব।)

আমাদের ঐ যে ‘ওয়ালটন উস্তা’ ক্লাসটা, এটা দিয়ে আমরা কিন্তু লাখ লাখ গাড়ি তৈরি করতে পারি। প্রতিটা গাড়িতেই কিন্তু ঐ চারটা ফাংশন থাকবে। এখন আমাদের গাড়িটার কথা ধরি। আমাদের গাড়িটাও তো ‘ওয়ালটন উস্তা’ ক্লাস থেকে তৈরি। তাহলে আমাদের গাড়িটা হল ঐ ক্লাসের একটা অবজেক্ট। ঐ ক্লাস থেকে তৈরি সব গাড়িই এক-একটা অবজেক্ট।

চলুন সবাই মিলে পাইথনিক উপায়ে ‘ওয়ালটন উস্তা’র অবজেক্ট তৈরি করি।

our_car = WaltonUsta()
her_car = WaltonUsta()
your_car = WaltonUsta()

এখানে our_car, her_car, your_car সবগুলো হল অবজেক্ট, WaltonUsta() ক্লাসের অবজেক্ট। আর প্রতিটা অবজেক্টই কিন্তু ক্লাসের সব ফাংশনকে অ্যাক্সেস করতে পারবে।

মেথড (Method) কী?

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

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

এখন আমরা বাস্তব একটা উদাহরণ দেখব। আমরা ক্যালকুলেটরের জন্য একটা ক্লাস তৈরি করব। এই ক্লাসে যোগ, বিয়োগ, গুণ ও ভাগের জন্য মেথড থাকবে।

class Calculator:
    """Do addition, subtraction, multiplication and division."""

    def addition(self, a, b):
        return a+b

    def subtraction(self, a, b):
        return a-b

    def multiplication(self, a, b):
        return a*b

    def division(self, a, b):
        try:
            return a/b
        except ZeroDivisionError:
            return 'It is impossible to divide by zero.'

my_calculator = Calculator()

temp = my_calculator.addition(12, 78)
print(temp)

temp = my_calculator.subtraction(50, 23)
print(temp)

temp = my_calculator.multiplication(9, 19)
print(temp)

temp = my_calculator.division(400, 5)
print(temp)

temp = my_calculator.division(43, 0)
print(temp)

আউটপুট

90
27
171
80.0
It is impossible to divide by zero.

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

যদি আমরা ক্লাসের ভিতর কোন ভ্যালু পাস করতে চাই? আর পরে যদি সেই ভ্যালু নিয়েই মেথডের ভিতর কোডিং কারিশমা ফলাতে চাই? তখন ক্লাসের প্রথম মেথড হিসাবে __init__ ব্যবহার করতে হবে। প্রোগ্রামিংয়ের ভাষায় একে ক্লাস কনস্ট্রাক্টর (constructor) বলে। যখন কোন ক্লাসের নতুন ইন্সট্যান্স বা অবজেক্ট তৈরি করি আমরা তখন পাইথন নিজ থেকেই ক্লাস কনস্ট্রাক্টরকে কল করে। ওহ! যখন ক্লাস কনট্রাক্টর আমরা ডিফাইন করি না তখন পাইথন নিজ থেকেই ক্লাস কনস্ট্রাক্টর ডিফাইন করে নেয়।

চটপট একটা উদাহরণ দেখা যাক।

class Calculator:
    """Do addition, subtraction, multiplication and division."""

    def __init__(self, a, b):
        self.a = a
        self.b = b

    def addition(self):
        return self.a + self.b

    def subtraction(self):
        return self.a - self.b

    def multiplication(self):
        return self.a * self.b

    def division(self):
        try:
            return self.a / self.b
        except ZeroDivisionError:
            return 'It is impossible to divide by zero.'

my_calculator = Calculator(45, 3)

temp = my_calculator.addition()
print(temp)

temp = my_calculator.subtraction()
print(temp)

temp = my_calculator.multiplication()
print(temp)

temp = my_calculator.division()
print(temp)

আউটপুট

48
42
135
15.0

আমরা __init__ ব্লকটা রিভিউ করি একটু। বাধ্যতামূলক self বাদে আমরা আরো দুইটা প্যারামিটার a, b দিয়েছি। তারপর self.a তে a এর ভ্যালু ও self.b তে b এর ভ্যালু অ্যাসাইন করেছি। এর ফলে a, b এর ভ্যালু self.a, self.b এর মাধ্যমে পুরো ক্লাসের ভিতর অ্যাক্সেসিবল হয়ে গেল।

এবার ইনস্ট্যান্স বা অবজেক্ট ক্রিয়েশনটা রিভিউ করি। my_calculator অবজেক্ট তৈরির সময় আমরা Calculator এর ভিতর দুইটা ভ্যালু পাস করেছি। এটার সাথে __init__ মেথডের যোগসাজশ আছে। এই ভ্যালু দুইটা সরাসরি __init__ এর ভিতর চলে আসে। সহজ কথায়, __init__ বা ক্লাস কনস্ট্রাক্টরের প্যারামিটারই ক্লাসের প্যারামিটার।

এই চাপ্টার তো অনেক লম্বা হয়ে গেল। তাহলে আপাতত এই চাপ্টার এখানেই মূলতবি ঘোষণা থাকুক।

comments powered by Disqus