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 RuntimeError
khô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 Exception
s. Vì vậy, nếu bạn tăng một Exception
mã của mình, mã này sẽ không bắt được nó:
begin
rescue
end
Để nắm bắt Exception
bạ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 đó, Exception
lỗ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à rescue
khố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 RuntimeError
là một lớp con của StandardError
lớ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 rescue
sẽ 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 RuntimeError
if $!
là nil. Với một String
đối số duy nhất , nó tăng a RuntimeError
vớ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 Exception
lớp (hoặc một đối tượng trả về Exception
ngoạ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...end
cá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?