ما الفرق بين رفع الاستثناءات ورمي الاستثناءات في روبي؟
سؤال
لدى روبي آليتان مختلفتان للاستثناءات:رمي/قبض ورفع/إنقاذ.
لماذا لدينا اثنان؟
متى يجب عليك استخدام واحد وليس الآخر؟
المحلول
أظن http://hasno.info/Ruby-gotchas-and-caveats لديه تفسير لائق للفرق:
الالتقاط/الرمي ليس مثل الرفع/الإنقاذ.يسمح لك الالتقاط/الرمي بالخروج بسرعة من الكتل مرة أخرى إلى النقطة التي يتم فيها تعريف الالتقاط لرمز معين، ويعتبر رفع الإنقاذ هو الاستثناء الحقيقي للتعامل مع الأشياء التي تتضمن كائن الاستثناء.
نصائح أخرى
raise
,fail
,rescue
, ، وensure
مقبض أخطاء, ، المعروف أيضًا باسم استثناءاتthrow
وcatch
نكون تدفق التحكم
على عكس اللغات الأخرى ، لا يتم استخدام رمية Ruby و Catch للاستثناءات.بدلاً من ذلك ، فإنها توفر وسيلة لإنهاء التنفيذ مبكرًا عند عدم الحاجة إلى مزيد من العمل.(جريم، 2011)
إنهاء مستوى واحد من تدفق التحكم، مثل while
حلقة، يمكن القيام بها بطريقة بسيطة return
.يمكن إنهاء العديد من مستويات تدفق التحكم، مثل الحلقة المتداخلة throw
.
على الرغم من أن آلية الاستثناء الخاصة بالرفع والإنقاذ تعتبر رائعة للتخلي عن التنفيذ عندما تسوء الأمور، إلا أنه من الجيد أحيانًا أن تكون قادرًا على القفز من بعض البنية المتداخلة أثناء المعالجة العادية.هذا هو المكان الذي يكون فيه الإمساك والرمي مفيدًا.(توماس وهانت، 2001)
مراجع
- جريم، افيدي."رمي ، اصطياد ، ارفع ، إنقاذ ... أنا مرتبك للغاية!" مدونة Rubylearning.ن.ب، 11 يوليو 2011.ويب.1 يناير2012. http://rubylearning.com/blog/2011/07/12/throw-catch-raise-rescue--im-so-confused/.
- توماس وديف وأندرو هانت."برمجة روبي." :دليل المبرمج العملي.ن.ب، 2001.ويب.29 سبتمبر2015. http://Ruby-doc.com/docs/ProgrammingRuby/html/tut_exceptions.html.
https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise يقدم شرحًا ممتازًا وأشك في أنني أستطيع تحسينه.لتلخيص ذلك، أخذ بعض نماذج التعليمات البرمجية من منشور المدونة بينما أذهب:
raise
/rescue
هي أقرب نظائرها إلىthrow
/catch
البناء الذي تعرفه من اللغات الأخرى (أو من لغة Pythonraise
/except
).إذا واجهت حالة خطأ وسوف تفعل ذلكthrow
أكثر من ذلك بلغة أخرى، يجب عليكraise
في روبي.روبي
throw
/catch
يتيح لك كسر التنفيذ وتسلق المكدس بحثًا عن ملفcatch
(يحبraise
/rescue
يفعل)، ولكن ليس المقصود حقًا حالات الخطأ.يجب استخدامه نادرًا، وهو موجود فقط عند "السير في المكدس حتى تجد ملفًا مطابقًاcatch
"السلوك منطقي بالنسبة للخوارزمية التي تكتبها ولكن لن يكون من المنطقي التفكير فيthrow
بما يتوافق مع حالة الخطأ.ما هو الصيد والرمي المستخدم في روبي؟ يقدم بعض الاقتراحات حول الاستخدامات الجيدة لـ
throw
/catch
بناء.
تشمل الاختلافات السلوكية الملموسة بينهما ما يلي:
rescue Foo
سوف ينقذ حالاتFoo
بما في ذلك الفئات الفرعية منFoo
.catch(foo)
سوف يمسك فقط نفس الكائن،Foo
.ليس فقط لا يمكنك المرورcatch
اسم فئة لالتقاط مثيلات منه، لكنه لن يقوم حتى بإجراء مقارنات المساواة.على سبيل المثالcatch("foo") do throw "foo" end
سوف أعطيك
UncaughtThrowError: uncaught throw "foo"
(أوArgumentError
في إصدارات روبي قبل 2.2)يمكن إدراج شروط الإنقاذ المتعددة...
begin do_something_error_prone rescue AParticularKindOfError # Insert heroism here. rescue write_to_error_log raise end
بينما متعددة
catch
يجب أن تكون متداخلة ...catch :foo do catch :bar do do_something_that_can_throw_foo_or_bar end end
عارية
rescue
يعادلrescue StandardError
وهو بناء اصطلاحي.عاريةcatch
"، يحبcatch() {throw :foo}
, ، لن يمسك أي شيء أبدًا ولا ينبغي استخدامه.