¿Cuál es la diferencia - técnica, filosófica, conceptual o de otro tipo - entre
raise "foo"
y
raise Exception.new("foo")
?
¿Cuál es la diferencia - técnica, filosófica, conceptual o de otro tipo - entre
raise "foo"
y
raise Exception.new("foo")
?
Respuestas:
Técnicamente, el primero genera un RuntimeError con el mensaje configurado en "foo"
, y el segundo genera una Excepción con el mensaje configurado en "foo"
.
En la práctica, existe una diferencia significativa entre cuándo desearía usar el primero y cuándo desea usar el segundo.
En pocas palabras, probablemente quieras un RuntimeError
not an Exception
. Un bloque de rescate sin un argumento capturará RuntimeErrors
, pero NO capturará Exception
s. Entonces, si genera un Exception
en su código, este código no lo detectará:
begin
rescue
end
Para atraparlo Exception
tendrás que hacer esto:
begin
rescue Exception
end
Esto significa que, en cierto sentido, an Exception
es un error "peor" que a RuntimeError
, porque tiene que trabajar más para recuperarse.
Entonces, lo que quieras depende de cómo tu proyecto maneje los errores. Por ejemplo, en nuestros demonios, el bucle principal tiene un rescate en blanco que los detectará RuntimeErrors
, los reportará y luego continuará. Pero en una o dos circunstancias, queremos que el demonio realmente muera por un error, y en ese caso generamos un Exception
, que pasa directamente por nuestro "código normal de manejo de errores" y sale.
Y nuevamente, si está escribiendo código de biblioteca, probablemente desee un RuntimeError
, no un Exception
, ya que los usuarios de su biblioteca se sorprenderán si genera errores que un rescue
bloque en blanco no puede detectar, y les llevará un momento darse cuenta de por qué.
Finalmente, debo decir que RuntimeError
es una subclase de la StandardError
clase, y la regla real es que, aunque puede raise
cualquier tipo de objeto, el espacio en blanco rescue
solo capturará por defecto cualquier cosa que herede StandardError
. Todo lo demás tiene que ser específico.
StandardError
. No tiene por qué ser más complicado que unas pocas líneas como class MissingArgumentsError < StandardError; end
.
raise
raise( string )
raise( exception [, string [, array ] ] )
Sin argumentos, genera la excepción en $!
o genera un RuntimeError
if $!
es nil. Con un solo String
argumento, genera un RuntimeError
con la cadena como mensaje. De lo contrario, el primer parámetro debe ser el nombre de una Exception
clase (o un objeto que devuelve una Exception
excepción cuando se envía). El segundo parámetro opcional establece el mensaje asociado con la excepción y el tercer parámetro es una matriz de información de devolución de llamada. Las excepciones están atrapadas por la cláusula de rescate de begin...end
bloques.
raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
RuntimeError < StandardError < Exception
[2], por lo tanto, que el segundo bloque de código va a coger tanto una excepción y un RuntimeError [3] Es interesante / extraño que la subida y el rescate "desnudos" funcionen con esa Excepción en particular [4]. Quizás la regla general sea elevar RuntimeError al código del cliente, pero ¿generar y rescatar las propias Excepciones personalizadas dentro del propio código?