আপনি যদি রুবির এক্সেপশন নিয়ে আগে কাজ করে থাকেন, তবে আপনি জানেন আপনি নির্দিষ্ট করতে পারেন কোন এক্সেপশন রescu হবে এবং কোনটি হবে না:
begin
raise ArgumentError
rescue ArgumentError
# `ArgumentError` রescu করে
end
...এবং আপনি সম্ভবত জানেন যে যখন আপনি একটি "পেরেন্ট" রescu করেন, তবে আপনি তার সকল "চাইল্ড"-ও রescu করেন।
begin
raise ArgumentError
rescue StandardError
# `ArgumentError` রescu করে, কারণ এটি ইনহেরিট করে
# `StandardError`- থেকে
end
যখন আমি "পেরেন্ট" এবং "চাইল্ড" বলি, আমি সাদা ক্লাস ইনহেরিটেন্সকে বোঝাচ্ছি। রুবি সোর্স কোডের গভীরে কিছুটা এরকম আছে:
class ArgumentError < StandardError
...
end
একটি রোমাঞ্চক ট্রিক
আমার প্রশ্ন: রুবি কীভাবে জানে কোনো প্রদত্ত এক্সেপশন আপনি যে ক্লাস নির্দিষ্ট করেছেন তার থেকে ইনহেরিট করেছে কিনা?
সবচেয়েस्पষ্ট পদ্ধতি হলো is_a? বা kind_of? মেথড ব্যবহার করা। আমরা কল্পনা করতে পারি এটিইরকম দেখাবে:
if the_exception.is_a?(StandardError)
# do the rescue
end
কিন্তু এটি হয় না। বদলে, রুবি আরও আকর্ষণীয় === অপারেটর ব্যবহার করে।
if StandardError === the_exception
# do the rescue
end
আপনি যদি কখনো a === b ব্যবহার না করে থাকেন, তবে এটি সাধারণত এই প্রশ্নের উত্তর দেয় "কি a inherentভাবে b-র 의해 ডিফাইন করা গ্রুপের جزءًا?" কিছু উদাহরণ:
(1..10) === 5 # true
('a'..'f') === "z" # false
String === "hello" # true
String === 1 # false
/[0-9]{3}/ === "hello123" # true
/[0-9]{3}/ === "hello" # false
কারণ === শুধু একটি সাধারণ রুবি মেথড ==-এর মত, আমরা এটিকে নিজেদের ডিফাইন করতে পারি:
class RedThings
def self.===(thing)
thing.color == :red
end
end
তাহলে, আমরা কী জানি? আমরা জানি rescue === ব্যবহার করে নির্ধারণ করে কোন এক্সেপশনগুলো রescu হবে। এবং আমরা জানি আমরা নিজেদের === মেথড ডিফাইন করতে পারি। এর মানে আমরা একটি ক্লাস তৈরি করতে পারি যা অন-দ-ফ্লাই 決定 করবে কোন এক্সেপশনগুলো রescu হবে:
class SevereMatcher
def self.===(exception)
exception.message =~ /severe/
end
end
begin
raise RuntimeError, "Something severe happened"
rescue SevereMatcher
# ক্লাস নির্বিশেষে "severe" শব্দ সহ সকল এক্সেপশন রescu করে
end
এই ট্রিক জানার পর, একমাত্র সীমা আপনার কল্পনাশক্তি।
উপসংহার
আমি স্বীকার করছি: আপনার কখনো ডাইনামিক এক্সেপশন ম্যাচার তৈরি করার দরকার নাও হতে পারে। কিন্তু এটি একটি খুব আকর্ষণীয় উদাহরণ যে কীভাবে একটি বিচিত্র ইমপ্লিমেন্টেশন ডিটেইল যেমন kind_of? এর বদলে === ব্যবহার করা রুবিকে অনেক বেশি ফ্লেক্সিবল এবং আকর্ষণীয় করে তোলে।