Qual é a diferença - técnica, filosófica, conceitual ou outra - entre
raise "foo"
e
raise Exception.new("foo")
?
Qual é a diferença - técnica, filosófica, conceitual ou outra - entre
raise "foo"
e
raise Exception.new("foo")
?
Respostas:
Tecnicamente, o primeiro gera um RuntimeError com a mensagem definida como "foo"e o segundo gera uma Exceção com a mensagem definida como "foo".
Praticamente, há uma diferença significativa entre quando você deseja usar o primeiro e quando deseja usar o último.
Simplificando, você provavelmente RuntimeErrornão deseja um Exception. Um bloco de resgate sem um argumento pegará RuntimeErrors, mas NÃO pegará Exceptions. Portanto, se você gerar um Exceptionem seu código, este código não o pegará:
begin
rescue
end
Para capturar o, Exceptionvocê terá que fazer o seguinte:
begin
rescue Exception
end
Isso significa que, em certo sentido, um Exceptioné um erro "pior" do que um RuntimeError, porque você precisa trabalhar mais para se recuperar dele.
Portanto, o que você deseja depende de como seu projeto trata de erros. Por exemplo, em nossos daemons, o loop principal tem um resgate em branco que os captura RuntimeErrors, relata e depois continua. Mas em uma ou duas circunstâncias, queremos que o daemon realmente morra com um erro e, nesse caso, levantamos um Exception, que vai direto ao nosso "código normal de tratamento de erros" e sai.
E, novamente, se você está escrevendo o código da biblioteca, provavelmente deseja um RuntimeError, não um Exception, pois os usuários de sua biblioteca ficarão surpresos se isso gerar erros que um rescuebloco em branco não pode detectar, e eles levarão um momento para perceber o porquê.
Finalmente, devo dizer que RuntimeErroré uma subclasse da StandardErrorclasse, e a regra real é que, embora você possa raise qualquer tipo de objeto, o espaço rescueem branco , por padrão, só capturará qualquer coisa que herde de StandardError. Todo o resto tem que ser específico.
StandardError. Não precisa ser mais complicado do que algumas linhas como class MissingArgumentsError < StandardError; end.
raise
raise( string )
raise( exception [, string [, array ] ] )
Sem argumentos, levanta a exceção em $!ou levanta um RuntimeErrorse $!for nulo. Com um único Stringargumento, ele gera a RuntimeErrorcom a string como uma mensagem. Caso contrário, o primeiro parâmetro deve ser o nome de uma Exceptionclasse (ou um objeto que retorna uma Exceptionexceção quando enviada). O segundo parâmetro opcional define a mensagem associada à exceção e o terceiro parâmetro é uma matriz de informações de retorno de chamada. As exceções são capturadas pela cláusula de resgate de begin...endblocos.
raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
RuntimeError < StandardError < Exception[2] portanto, que segundo bloco de código vai pegar tanto uma exceção e uma RuntimeError [3] é interessante / estranho que o aumento e o resgate "simples" aconteçam para funcionar com aquela Exception em particular [4]. Talvez a regra seja aumentar RuntimeError para o código do cliente, mas aumentar e resgatar as próprias Exceptions personalizadas dentro do próprio código?