이전에 Ruby의 예외로 작업한 적이 있다면 어떤 예외가 구제되고 어떤 예외가 발생하지 않는지 지정할 수 있습니다.
begin
raise ArgumentError
rescue ArgumentError
# Rescues the `ArgumentError`
end
... "부모"를 구하면 모든 "자식"도 구한다는 것을 알고 있을 것입니다.
begin
raise ArgumentError
rescue StandardError
# Rescues `ArgumentError`, because it inherits from
# `StandardError`
end
내가 "부모"와 "자식"이라고 말할 때 나는 단순히 클래스 상속을 언급하고 있습니다. 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
를 사용한 적이 없는 경우 , 일반적으로 "본질적으로 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?
대신 Ruby를 훨씬 더 유연하고 흥미롭게 만듭니다.