আজ আমি self নিয়ে কথা বলতে চাই। আপনি যদি কিছুক্ষণ ধরে রুবি প্রোগ্রামিং করেন, তবে আপনি সম্ভবত self কনসেপ্টটি ইন্টারনালাইজ করেছেন। আপনি যখন কোনো প্রোগ্রাম পড়েন বা লিখেন, self আপনার মस्तিষ্কের পিছনে থাকে।
কম অভিজ্ঞ রুবিস্টদের জন্য self বিভ্রান্তিকর হতে পারে। এটি সবসময় পরিবর্তন হয়, কিন্তু কোডে কখনো এক্সপ্লিসিটলি দেখায় না। আপনাকে শুধু জানতে হবে।
শুরুকারীদের অনেক সমস্যা self না বুঝার কারণে হয়। আপনি যদি কখনো একটি ইনস্ট্যান্স ভেরিয়েবল "হেরে যান" বা মিক্সিনে কী ডেটা ভিজিবল তা নিয়ে হতবুদ্ধি হন, তবে এর কারণ আপনি সেটি কনটেক্সটে self বুঝতে পারেননি।
এই পোস্টে, আমরা self কে বিভিন্ন দৈনন্দিন পরিস্থিতিতে দেখব।
self কী?
আপনি শুনেছেন থাকতে পারে যে রুবিতে সব কিছু অবজেক্ট। যদি সেটি সত্য হয়, তবে আপনি যা লিখেন সেটি কোনো অবজেক্টের "স্বামিত্ব" করে।
self একটি স্পেশাল ভেরিয়েবল যা বর্তমানে এক্সিকিউট হচ্ছে কোডটির "মালিক" অবজেক্টকে পয়েন্ট করে। রুবি self সব জায়গায় ব্যবহার করে:
- ইনস্ট্যান্স ভেরিয়েবলের জন্য:
@myvar - মেথড এবং কনস্টান্ট লুকআপের জন্য
- মেথড, ক্লাস এবং মডিউল ডেফাইন করার সময়
তئোরিতে, self খুব স্পষ্ট। কিন্তু প্র্যাকটিসে, ট্রিকি পরিস্থিতি আসা সহজ। তাই আমি এই পোস্ট লিখলাম।
self উদাহরণ
আমরা এখন چندین উদাহরণে যাব। যদি প্রথমগুলো আপনার জন্য খুব বেসিক লাগে, পড়তে থাকুন। এগিয়ে যাওয়ার সাথে সাথে এডভান্সড হয়ে যাবে।
ইনস্ট্যান্স মেথডের ভেতরে
নিচের কোডে, reflect একটি ইনস্ট্যান্স মেথড। এটি उस অবজেক্টের বেলং করে যা Ghost.new দিয়ে তৈরি করা হয়েছে। তাই self সেই অবজেক্টকে পয়েন্ট করে।
class Ghost
def reflect
self
end
end
g = Ghost.new
g.reflect == g # => true
ক্লাস মেথডের ভেতরে
এই উদাহরণে, reflect হলো Ghost-এর একটি ক্লাস মেথড। ক্লাস মেথডের সাথে, ক্লাসটি নিজে মেথডটি "মালিকানা" করে। self ক্লাসকে পয়েন্ট করে।
class Ghost
def self.reflect
self
end
end
Ghost.reflect == Ghost # => true
মডিউলের ভেতরের "ক্লাস" মেথডের সাথেও একইভাবে কাজ করে। উদাহরণস্বরূপ:
module Ghost
def self.reflect
self
end
end
Ghost.reflect == Ghost # => true
মনে রাখবেন, ক্লাস এবং মডিউল রুবিতে অবজেক্ট হিসেবে ট्रीট হয়। তাই এই আচরণ প্রথম উদাহরণের ইনস্ট্যান্স মেথড আচরণ থেকে তত ভিন্ন নয়।
ক্লাস বা মডিউল ডেফিনিশনের ভেতরে
রুবির একটি ফিচার যা এটিকে রেইলস এরような ফ্রেমওয়ার্কের জন্য খুব উপযুক্ত করে তোলে সেটি হচ্ছে আপনি ক্লাস এবং মডিউল ডেফিনিশনের ভেতরে আর্বিট্রারি কোড এক্সিকিউট করতে পারেন। আপনি যখন ক্লাস/মডিউল ডেফিনিশনের ভেতরে কোড রাখেন, সেটি অন্য যেকোনো রুবি কোডের মতো চলে। একমাত্র আসল পার্থক্য হচ্ছে self-এর মান।
নিচে দেখুন, self সেটি ক্লাস বা মডিউলকে পয়েন্ট করে যা ডেফাইন হচ্ছে।
class Ghost
self == Ghost # => true
end
module Mummy
self == Mummy # => true
end
মিক্সিন মেথডের ভেতরে
মিক্সড-ইন মেথড self বিষয়ে "নরমাল" ইনস্ট্যান্স বা ক্লাস মেথডের মতোই আচরণ করে। এটি অর্থহীন। অন্যথায় মিক্সিন ক্লাসের সাথে ইন্টারঅ্যাক্ট করতে পারত না যেটি এটিকে মিক্স ইন করা হয়েছে।
ইনস্ট্যান্স মেথড
reflect মেথডটি মডিউলে ডেফাইন করা হলেও, এর self হলো সে ক্লাসের ইনস্ট্যান্স যেটিতে এটি মিক্স ইন করা হয়েছে।
module Reflection
def reflect
self
end
end
class Ghost
include Reflection
end
g = Ghost.new
g.reflect == g # => true
ক্লাস মেথড
যখন আমরা extend করি একটি ক্লাসকে ক্লাস মেথড মিক্স ইন করার জন্য, self নরমাল ক্লাস মেথডের মতোই আচরণ করে।
module Reflection
def reflect
self
end
end
class Ghost
extend Reflection
end
Ghost.reflect == Ghost # => true
মেটাক্লাসের ভেতরে
সম্ভবত আপনি এই পপুলার শর্টকাটটি দেখেছেন অনেক ক্লাস মেথড একসাথে ডেফাইন করার জন্য।
class Ghost
class << self
def method1
end
def method2
end
end
end
class << foo সিনট্যাক্স আসলে খুব আকর্ষণীয়। এটি আপনাকে একটি অবজেক্টের মেটাক্লাস এক্সেস করতে দেয়—যা "সিঙ্গলটন ক্লাস" বা "আইজেনক্লাস" ও বলা হয়। আমি ভবিষ্যতে মেটাক্লাসে আরও গভীরে আলোচনা করব। কিন্তু এখন, আপনার জানতে হবে যে মেটাক্লাস হলো সেখানে রুবি সেভ করে যেসব মেথড একটি নির্দিষ্ট অবজেক্টের জন্য ইউনিক।
আপনি যদি class << foo ব্লকের ভেতরে থেকে self অ্যাক্সেস করেন, তবে আপনি মেটাক্লাস পাবেন।
class << "test"
puts self.inspect
end
# => #<Class:#<String:0x007f8de283bd88>>
যেকোনো ক্লাসের বাইরে
আপনি যদি কোনো ক্লাসের বাইরে কোড রান করেন, রুবি এখনো self দিয়ে থাকে। এটি "main"-কে পয়েন্ট করে, যা Object-এর একটি ইনস্ট্যান্স:
puts self.inspect
# => main