Jaka jest różnica - techniczna, filozoficzna, konceptualna lub inna - między
raise "foo"
i
raise Exception.new("foo")
?
Jaka jest różnica - techniczna, filozoficzna, konceptualna lub inna - między
raise "foo"
i
raise Exception.new("foo")
?
Odpowiedzi:
Technicznie rzecz biorąc, pierwszy wywołuje RuntimeError z komunikatem ustawionym na "foo"
, a drugi zgłasza wyjątek z komunikatem ustawionym na "foo"
.
Praktycznie istnieje znacząca różnica między tym, kiedy chcesz użyć pierwszego, a kiedy chcesz użyć drugiego.
Mówiąc najprościej, prawdopodobnie chcesz mieć RuntimeError
nie Exception
. Blok ratunkowy bez argumentu złapie RuntimeErrors
, ale NIE złapie Exception
s. Więc jeśli podniesiesz an Exception
w swoim kodzie, ten kod go nie złapie:
begin
rescue
end
Aby go złapać Exception
, musisz to zrobić:
begin
rescue Exception
end
Oznacza to, że w pewnym sensie an Exception
jest „gorszym” błędem niż a RuntimeError
, ponieważ musisz wykonać więcej pracy, aby się z niego wyleczyć.
Więc to, co chcesz, zależy od tego, jak twój projekt obsługuje obsługę błędów. Na przykład w naszych demonach główna pętla ma pusty ratunek, który złapie RuntimeErrors
, zgłosi je, a następnie będzie kontynuował. Ale w jednej lub dwóch okolicznościach chcemy, aby demon naprawdę umarł z powodu błędu, iw takim przypadku wywołujemy an Exception
, który przechodzi prosto przez nasz „normalny kod obsługi błędów” i wychodzi.
I znowu, jeśli piszesz kod biblioteki, prawdopodobnie chcesz a RuntimeError
, a nie an Exception
, ponieważ użytkownicy Twojej biblioteki będą zaskoczeni, jeśli spowoduje to pojawienie się błędów, których pusty rescue
blok nie może przechwycić, i zajmie im chwilę, zanim zrozumieją, dlaczego.
Na koniec powinienem powiedzieć, że RuntimeError
jest podklasą tej StandardError
klasy, a aktualna zasada jest taka, że chociaż można obiektami raise
dowolnego typu, puste pole rescue
domyślnie przechwytuje tylko wszystko, co dziedziczy StandardError
. Wszystko inne musi być konkretne.
StandardError
. Nie musi to być bardziej skomplikowane niż kilka linijek class MissingArgumentsError < StandardError; end
.
raise
raise( string )
raise( exception [, string [, array ] ] )
Bez argumentów zgłasza wyjątek $!
lub podnosi RuntimeError
jeśli $!
jest równe zero. Za pomocą pojedynczego String
argumentu podnosi RuntimeError
ciąg znaków jako komunikat. W przeciwnym razie pierwszym parametrem powinna być nazwa Exception
klasy (lub obiekt, który zwraca Exception
wyjątek po wysłaniu). Opcjonalny drugi parametr ustawia komunikat skojarzony z wyjątkiem, a trzeci parametr jest tablicą informacji zwrotnych. Wyjątki są objęte klauzulą ratunkową begin...end
bloków.
raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
RuntimeError < StandardError < Exception
[2], w związku z tym, że drugi blok kodu będzie złapać zarówno wyjątek a RuntimeError [3] to ciekawe / dziwne, że „nagie” podniesienie i uratowanie działa z tym konkretnym Wyjątkiem [4]. Być może ogólną zasadą jest podniesienie RuntimeError do kodu klienta, ale podniesienie i uratowanie własnych niestandardowych wyjątków wewnątrz własnego kodu?