หากคุณเคยทำงานกับข้อยกเว้นของ Ruby มาก่อน คุณจะรู้ว่าคุณสามารถระบุได้ว่าข้อยกเว้นใดจะได้รับการช่วยเหลือและข้อยกเว้นใดบ้าง:
begin
raise ArgumentError
rescue ArgumentError
# Rescues the `ArgumentError`
end
...และคุณอาจรู้ว่าเมื่อคุณช่วย "พ่อแม่" คุณก็ช่วย "ลูกๆ" ของมันด้วยเช่นกัน
begin
raise ArgumentError
rescue StandardError
# Rescues `ArgumentError`, because it inherits from
# `StandardError`
end
เมื่อฉันพูดว่า "parent" และ "child" ฉันหมายถึงการสืบทอดคลาส ลึกลงไปในซอร์สโค้ดของ Ruby มีบางสิ่งที่เทียบเท่ากับสิ่งนี้:
class ArgumentError < StandardError
...
end
เคล็ดลับที่น่าสนใจ
นี่คือคำถามของฉัน:Ruby จะรู้ได้อย่างไรว่าข้อยกเว้นที่ได้รับมาจากคลาสที่คุณระบุหรือไม่
แนวทางที่ชัดเจนที่สุดคือการใช้ is_a?
หรือ kind_of?
กระบวนการ. เราสามารถจินตนาการว่ามันมีลักษณะเช่นนี้:
if the_exception.is_a?(StandardError)
# do the rescue
end
แต่นั่นไม่ใช่สิ่งที่เกิดขึ้น Ruby ใช้ ===
. ที่น่าสนใจกว่าแทน โอเปอเรเตอร์
if StandardError === the_exception
# do the rescue
end
หากคุณไม่เคยใช้ a === b
มักจะตอบคำถามว่า "a อยู่ในกลุ่มที่กำหนดโดย 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
ใช้ ===
เพื่อกำหนดข้อยกเว้นที่จะได้รับการช่วยเหลือ และเรารู้ว่าเราสามารถกำหนด ===
. ของเราเองได้ กระบวนการ. นั่นหมายความว่าเราสามารถสร้างชั้นเรียนที่ตัดสินใจได้ทันทีว่าข้อยกเว้นใดบ้างที่ได้รับการช่วยเหลือ:
class SevereMatcher
def self.===(exception)
exception.message =~ /severe/
end
end
begin
raise RuntimeError, "Something severe happened"
rescue SevereMatcher
# rescues all exceptions with the word "severe" in
# the message, regardless of class.
end
เมื่อคุณรู้เคล็ดลับนี้แล้ว ขีดจำกัดเพียงอย่างเดียวคือจินตนาการของคุณ
บทสรุป
ฉันจะยอมรับ:คุณอาจไม่จำเป็นต้องสร้างตัวจับคู่ข้อยกเว้นแบบไดนามิก แต่นี่เป็นตัวอย่างที่น่าสนใจมากว่ารายละเอียดการใช้งานที่ดูเหมือนเล็กน้อยเช่นการใช้ ===
แทนที่จะเป็น kind_of?
ทำให้ทับทิมมีความยืดหยุ่นและน่าสนใจมากขึ้น