Sự khác biệt là gì - kỹ thuật, triết học, khái niệm hoặc cách khác - giữa
raise "foo"
và
raise Exception.new("foo")
?
Sự khác biệt là gì - kỹ thuật, triết học, khái niệm hoặc cách khác - giữa
raise "foo"
và
raise Exception.new("foo")
?
Câu trả lời:
Về mặt kỹ thuật, lần đầu tiên tạo ra RuntimeError với thông báo được đặt thành "foo", và lần thứ hai tạo ra Ngoại lệ với thông báo được đặt thành "foo".
Thực tế, có một sự khác biệt đáng kể giữa thời điểm bạn muốn sử dụng cái trước và khi nào bạn muốn dùng cái sau.
Nói một cách đơn giản, bạn có thể muốn RuntimeErrorkhông phải là một Exception. Khối giải cứu không có đối số sẽ bắt RuntimeErrors, nhưng KHÔNG bắt được Exceptions. Vì vậy, nếu bạn tăng một Exceptionmã của mình, mã này sẽ không bắt được nó:
begin
rescue
end
Để nắm bắt Exceptionbạn sẽ phải làm điều này:
begin
rescue Exception
end
Điều này có nghĩa là theo một nghĩa nào đó, Exceptionlỗi là một lỗi "tồi tệ hơn" so với lỗi RuntimeError, bởi vì bạn phải làm nhiều việc hơn để khôi phục nó.
Vì vậy, điều bạn muốn phụ thuộc vào cách dự án của bạn xử lý lỗi của nó. Ví dụ, trong daemon của chúng tôi, vòng lặp chính có một giải cứu trống sẽ bắt RuntimeErrors, báo cáo chúng và sau đó tiếp tục. Nhưng trong một hoặc hai trường hợp, chúng tôi muốn daemon thực sự chết vì lỗi, và trong trường hợp đó, chúng tôi tăngException , đi thẳng qua "mã xử lý lỗi bình thường" của chúng ta và ra ngoài.
Và một lần nữa, nếu bạn đang viết mã thư viện, bạn có thể muốn RuntimeError chứ không phải an Exception, vì người dùng thư viện của bạn sẽ ngạc nhiên nếu nó phát sinh lỗi mà rescuekhối trống không thể bắt được và họ sẽ mất một chút thời gian để nhận ra lý do.
Cuối cùng, tôi nên nói rằng lớp RuntimeErrorlà một lớp con của StandardErrorlớp và quy tắc thực tế là mặc dù bạn có thể raise bất kỳ loại đối tượng nào, nhưng ô trống rescuesẽ theo mặc định chỉ bắt bất kỳ thứ gì kế thừa từ đó StandardError. Mọi thứ khác phải cụ thể.
StandardError. Nó không cần phải phức tạp hơn một vài dòng như thế class MissingArgumentsError < StandardError; end.
                    raise   
raise( string )
raise( exception [, string [, array ] ] )
Không có đối số, tăng ngoại lệ trong $!hoặc tăng một RuntimeErrorif $!là nil. Với một Stringđối số duy nhất , nó tăng a RuntimeErrorvới chuỗi dưới dạng một thông báo. Nếu không, tham số đầu tiên phải là tên của một Exceptionlớp (hoặc một đối tượng trả về Exceptionngoại lệ khi được gửi). Tham số thứ hai tùy chọn đặt thông báo được liên kết với ngoại lệ và tham số thứ ba là một mảng thông tin gọi lại. Các ngoại lệ được nắm bắt bởi điều khoản giải cứu của begin...endcác khối.
raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
              
RuntimeError < StandardError < Exception[2] do đó, khối mã thứ hai đó sẽ bắt được cả Exception và RuntimeError [3] Thật thú vị / kỳ lạ là việc tăng và cứu "trần" lại hoạt động với Ngoại lệ cụ thể đó [4] có lẽ quy tắc ngón tay cái là nâng RuntimeError lên mã máy khách, nhưng nâng và giải cứu các Ngoại lệ tùy chỉnh của riêng mình trong mã của riêng mình?