কম্পিউটার টিউটোরিয়াল

রুবি মেটাক্লাস মাস্টার করা: ক্লাস, ইনস্ট্যান্স এবং মেথড ডেফিনিশন বোঝা

রুবি ম্যাজিকের নতুন エピソードে স্বাগতম! এই মাসের এডিশন মেটাক্লাস নিয়ে, একটি বিষয় যেটি উদ্ভূত হয়েছে দুজন ডেভেলপারের ডিসকশন থেকে (হাই মড!)

মেটাক্লাস এক্সামিন করে, আমরা শিখব ক্লাস এবং ইনস্ট্যান্স মেথড রুবিতে কীভাবে কাজ করে। পথে, ডিসকভার করব এক্সপ্লিসিট "definee" পাস করে মেথড ডিফাইন করার 것과 class << self বা instance_eval ব্যবহার করার পার্থক্য। চলুন!

ক্লাস ইনস্ট্যান্স এবং ইনস্ট্যান্স মেথড

মেটাক্লাস রুবিতে কেন ব্যবহার হয় সেটা বোঝার জন্য, আমরা শুরু করব ইনস্ট্যান্স- এবং ক্লাস মেথডের পার্থক্য এক্সামিন করে।

রুবিতে, একটি ক্লাস একটি অবজেক্ট যা একটি ব্লুপ্রিন্ট ডিফাইন করে অন্য অবজেক্ট তৈরি করার জন্য। ক্লাসগুলো ডিফাইন করে কোন মেথডগুলো যেকোনো সেই ক্লাসের ইনস্ট্যান্সে উপলব্ধ থাকবে।

একটি ক্লাসের ভিতরে একটি মেথড ডিফাইন করা সেটার ওপর একটি ইনস্ট্যান্স মেথড তৈরি করে। সেই ক্লাসের যেকোনো ভবিষ্যত ইনস্ট্যান্সে সেই মেথডটি উপলব্ধ থাকবে।

class User def initialize(name) @name = name end def name @name end end user = User.new('Thijs') user.name # => "Thijs"

এই উদাহরণে, আমরা একটি ক্লাস তৈরি করেছি User নামে, একটি ইনস্ট্যান্স মেথড নামে #name যা ইউজারের নাম রিটার্ন করে। ক্লাস ব্যবহার করে, আমরা তারপর একটি ক্লাস ইনস্ট্যান্স তৈরি করি এবং সেটি একটি ভেরিয়েবলে স্টোর করি user নামে। যেহেতু user User ক্লাসের একটি ইনস্ট্যান্স, এতে #name মেথড উপলব্ধ।

একটি ক্লাস তার ইনস্ট্যান্স মেথডগুলো তার মেথড টেবিল-এ সংরক্ষণ করে। সেই ক্লাসের যেকোনো ইনস্ট্যান্স তার ক্লাসের মেথড টেবিল রেফার করে তার ইনস্ট্যান্স মেথডগুলো অ্যাক্সেস করার জন্য।

ক্লাস অবজেক্ট

এক ক্লাস মেথড হলো একটি মেথড যা সরাসরি ক্লাসে কল করা যেতে পারে বিনা ইনস্ট্যান্স তৈরি किए। একটি ক্লাস মেথড তৈরি হয় এর নামের সাথে self. প্রিফিক্স দিয়ে ডিফাইন করার সময়।

একটি ক্লাস নিজে একটি অবজেক্ট। একটি কনস্ট্যান্ট ক্লাস অবজেক্টকে রেফার করে, তাই এতে ডিফাইন করা ক্লাস মেথডগুলো অ্যাপ্লিকেশনের যেকোনো জায়গা থেকে কল করা যাবে।

class User # ... def self.all [new("Thijs"), new("Robert"), new("Tom")] end end User.all # => [#<User:0x00007fb01701efb8 @name="Thijs">, #<User:0x00007fb01701ef68 @name="Robert">, #<User:0x00007fb01701ef18 @name="Tom">]

self.-প্রিফিক্স সহ ডিফাইন করা মেথডগুলো ক্লাসের মেথড টেবিলে যোগ হয় না। সেগুলো বদলে ক্লাসের মেটাক্লাসে যোগ হয়।

মেটাক্লাস

একটি ক্লাসের পাশাপাশি, রুবিতে প্রতিটি অবজেক্টের একটি লুকানো মেটাক্লাস থাকে। মেটাক্লাস সিঙ্গলটন, অর্থাৎ সেগুলো একটি একক অবজেক্টের জন্য বা লং। আপনি যদি একাধিক ইনস্ট্যান্স তৈরি করেন একটি ক্লাসের, সেগুলো একই ক্লাস শেয়ার করবে, কিন্তু সেগুলোর আলাদা আলাদা মেটাক্লাস থাকবে।

thijs, robert, tom = User.all thijs.class # => User robert.class # => User tom.class # => User thijs.singleton_class # => #<Class:#<User:0x00007fb71a9a2cb0>> robert.singleton_class # => #<Class:#<User:0x00007fb71a9a2c60>> tom.singleton_class # => #<Class:#<User:0x00007fb71a9a2c10>>

এই উদাহরণে, আমরা দেখতে পাচ্ছি যে যদিও প্রতিটি অবজেক্টের ক্লাস User, তাদের সিঙ্গলটন ক্লাসের আলাদা অবজেক্ট আইডি আছে, অর্থাৎ সেগুলো আলাদা অবজেক্ট।

মেটাক্লাসে অ্যাক্সেস থাকায়, রুবি একটি এক্সিস্টিং অবজেক্টে সরাসরি মেথড যোগ করার অনুমতি দেয়। এটি করলে অবজেক্টের ক্লাসে কোনো নতুন মেথড যোগ হয় না।

robert = User.new("Robert") def robert.last_name "Beekman" end robert.last_name # => "Beekman" User.new("Tom").last_name # => NoMethodError (undefined method `last_name' for #<User:0x00007fe1cb116408>)

এই উদাহরণে, আমরা robert ভেরিয়েবলে সংরক্ষিত ইউজারের সাথে #last_name যোগ করলাম। যদিও robert User-এর একটি ইনস্ট্যান্স, যেকোনো নতুন তৈরি User ইনস্ট্যান্স #last_name মেথড অ্যাক্সেস করতে পারবে না, কারণ এটি শুধু robert-এর মেটাক্লাসে এক্সিস্ট করে।

self কী?

যখন একটি মেথড ডিফাইন করা হয় এবং একটি রিসিভার পাস করা হয়, নতুন মেথডটি রিসিভারের মেটাক্লাসে যোগ হয়, ক্লাসের মেথড টেবিলে যোগ হওয়ার বদলে।

tom = User.new("Tom") def tom.last_name "de Bruijn" end

উপরোক্ত উদাহরণে, আমরা #last_name সরাসরি tom অবজেক্টে যোগ করলাম, tom-কে রিসিভার হিসেবে পাস করে মেথড ডিফাইন করার সময়।

এটি ক্লাস মেথডের জন্যও একইভাবে কাজ করে।

class User # ... def self.all [new("Thijs"), new("Robert"), new("Tom")] end end

এখানে, আমরা এক্সপ্লিসিটলি self-কে রিসিভার হিসেবে পাস করলাম .all মেথড তৈরি করার সময়। একটি ক্লাস ডেফিনিশনে, self ক্লাসকে রেফার করে (User এই কেসে), তাই .all মেথডটি User-এর মেটাক্লাসে যোগ হয়।

যেহেতু User একটি অবজেক্ট যা একটি কনস্ট্যান্টে স্টোর করা থাকে, আমরা একই অবজেক্ট — এবং একই মেটাক্লাস — এক্সেস করব যখনই আমরা এটিকে রেফার করব।

মেটাক্লাস খোলা

আমরা শিখেছি যে ক্লাস মেথডগুলো ক্লাস অবজেক্টের মেটাক্লাসে মেথড। এটা জানায়, আমরা ক্লাস মেথড তৈরি করার কিছু অন্য টেকনিক দেখব যা আপনি দেখতে পাবেন।

class << self

যদিও এটি কিছুটা আউট অফ স্টাইল চলে গেছে, কিছু লাইব্রেরি class << self ব্যবহার করে ক্লাস মেথড ডিফাইন করতে। এই সিনট্যাক্স ট্রিক করেন্ট ক্লাসের মেটাক্লাস খুলে দেয় এবং সেটার সাথে সরাসরি ইন্টারঅ্যাক্ট করে।

class User class << self self # => #<Class:User> def all [new("Thijs"), new("Robert"), new("Tom")] end end end User.all # => [#<User:0x00007fb01701efb8 @name="Thijs">, #<User:0x00007fb01701ef68 @name="Robert">, #<User:0x00007fb01701ef18 @name="Tom">]

এই উদাহরণটি একটি ক্লাস মেথড তৈরি করে User.all নামে User-এর মেটাক্লাসে একটি মেথড যোগ করে। পূর্বে আমরা যে পদ্ধতিতে এক্সপ্লিসিটলি রিসিভার পাস করতাম মেথডের জন্য, সেটার বদলে আমরা self-কে সেট করলাম User-এর মেটাক্লাসে User-এর বদলে।

যে মত আমরা আগে শিখেছিলাম, এক্সপ্লিসিট রিসিভার ছাড়া যেকোনো মেথড ডেফিনিশন করেন্ট ক্লাসের ইনস্ট্যান্স মেথড হিসেবে যোগ হয়। ব্লকের ভিতরে, করেন্ট ক্লাস হলো User-এর মেটাক্লাস (#<Class:User>)।

instance_eval

আরেকটি অপশন হলো instance_eval ব্যবহার করা, যেটি একই কাজ করে একটি বড় পার্থক্যের সাথে। যদিও ক্লাসের মেটাক্লাস ব্লকে ডিফাইন করা মেথডগুলো রিসিভ করে, self মূল ক্লাসকে রেফার করে থাকে।

class User instance_eval do self # => User def all [new("Thijs"), new("Robert"), new("Tom")] end end end User.all # => [#<User:0x00007fb01701efb8 @name="Thijs">, #<User:0x00007fb01701ef68 @name="Robert">, #<User:0x00007fb01701ef18 @name="Tom">]

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

আমরা যা শিখলাম

আমরা শিখেছি যে ক্লাসগুলো একমাত্র অবজেক্ট যারা মেথড থাকতে পারে, এবং ইনস্ট্যান্স মেথডগুলো আসলে একটি অবজেক্টের মেটাক্লাসে মেথড। আমরা জানি class << self সাদা self সওয়াপ করে যাতে আপনি মেটাক্লাসে মেথড ডিফাইন করতে পারেন, এবং আমরা জানি instance_eval প্রায় একই কাজ করে (বिना self ছোঁয়া)।

যদিও আপনি এক্সপ্লিসিটলি মেটাক্লাসের সাথে কাজ করবেন না, রুবি এতেন ব্যাপকভাবে হুডের নিচে ব্যবহার করে। মেথড ডিফাইন করার সময় কী হয় সেটা জানা আপনাকে বুঝতে সাহায্য করতে পারে কেন রুবি এভাবে বर्तমান করে ( এবং কেন আপনাকে ক্লাস মেথডে self. প্রিফিক্স দিতে হয়)।

পড়ার জন্য ধন্যবাদ। আপনি যা পড়লেন সেটা পছন্দ হলে, আপনি Ruby Magic সাবস্ক্রাইব করতে পছন্দ করতে পারেন ই-মেইল পেতে যখন আমরা প্রায় মাসে একবার নতুন আর্টিকেল পাবলিশ করি।

  1. রুবিতে কাস্টোম এক্সেপশন মাস্টার করুন: ধাপে ধাপে গাইড

  2. প্রোগ্রামিং-এ ক্লাসের গুরুত্ব: কোড সংগঠন এবং অ্যাবস্ট্রাকশন বাড়ানো

  3. রুবির লুকানো রত্ন: Delegator এবং Forwardable মাস্টার করা

  4. Kafka দিয়ে রুবি অ্যাপস উন্নত করা: একটি প্রমাণিত Sidekiq সাকসেস স্টোরি