Ruby memiliki dua mekanisme pengecualian yang berbeda: Throw / Catch dan Naikkan / Rescue.
Kenapa kita punya dua?
Kapan sebaiknya Anda menggunakan satu dan bukan yang lain?
Ruby memiliki dua mekanisme pengecualian yang berbeda: Throw / Catch dan Naikkan / Rescue.
Kenapa kita punya dua?
Kapan sebaiknya Anda menggunakan satu dan bukan yang lain?
Jawaban:
Saya pikir http://hasno.info/ruby-gotchas-and-caveats memiliki penjelasan yang layak tentang perbedaan:
menangkap / melempar tidak sama dengan menaikkan / menyelamatkan. catch / throw memungkinkan Anda untuk dengan cepat keluar dari blok kembali ke titik di mana tangkapan didefinisikan untuk simbol tertentu, meningkatkan penyelamatan adalah pengecualian nyata yang menangani hal-hal yang melibatkan objek Pengecualian.
raisesangat mahal. throwtidak. Anggap throwsebagai menggunakan gotountuk keluar dari lingkaran.
raise, fail, rescue, Dan ensuremenangani kesalahan , juga dikenal sebagai pengecualianthrowdan catchyang aliran kontrolTidak seperti dalam bahasa lain, lemparan dan tangkapan Ruby tidak digunakan untuk pengecualian. Sebaliknya, mereka menyediakan cara untuk menghentikan eksekusi lebih awal ketika tidak ada pekerjaan lebih lanjut diperlukan. (Grimm, 2011)
Mengakhiri satu tingkat aliran kontrol, seperti whileloop, dapat dilakukan dengan sederhana return. Mengakhiri banyak level aliran kontrol, seperti loop bersarang, dapat dilakukan dengan throw.
Meskipun mekanisme pengecualian untuk meningkatkan dan menyelamatkan sangat bagus untuk mengabaikan eksekusi ketika ada kesalahan, terkadang bagus untuk dapat melompat keluar dari beberapa konstruksi yang bersarang selama pemrosesan normal. Di sinilah menangkap dan melempar berguna. (Thomas and Hunt, 2001)
https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise menawarkan penjelasan yang luar biasa yang saya ragu bisa saya tingkatkan. Untuk meringkas, menandai beberapa contoh kode dari posting blog saat saya pergi:
raiseSaya rescueadalah analog terdekat dengan throw/ catchkonstruksi yang Anda kenal dari bahasa lain (atau ke Python raise/ except). Jika Anda mengalami kondisi kesalahan dan Anda akan throwmemperbaikinya dalam bahasa lain, Anda harus raisemenggunakan Ruby.
Ruby throw/ catchmemungkinkan Anda menghentikan eksekusi dan memanjat tumpukan mencari catch(seperti raise/ rescuetidak), tetapi tidak dimaksudkan untuk kondisi kesalahan. Ini harus jarang digunakan, dan apakah ada hanya ketika "berjalan tumpukan sampai Anda menemukan yang sesuai catch" perilaku masuk akal untuk algoritma yang Anda tulis tetapi tidak masuk akal untuk memikirkan yang throwsesuai dengan kesalahan kondisi.
Apa yang digunakan untuk menangkap dan melempar di Ruby? menawarkan beberapa saran tentang penggunaan throw/ catchkonstruksi yang bagus.
Perbedaan perilaku konkret di antara mereka termasuk:
rescue Fooakan menyelamatkan instance dari Footermasuk subclass dari Foo. catch(foo)hanya akan menangkap objek yang samaFoo ,. Anda tidak hanya tidak dapat memberikan catchnama kelas untuk menangkap contohnya, tetapi bahkan tidak akan melakukan perbandingan kesetaraan. Misalnya
catch("foo") do
throw "foo"
end
akan memberi Anda UncaughtThrowError: uncaught throw "foo"(atau ArgumentErrorversi Ruby sebelum 2.2)
Beberapa klausul penyelamatan dapat dicantumkan ...
begin
do_something_error_prone
rescue AParticularKindOfError
# Insert heroism here.
rescue
write_to_error_log
raise
end
sementara beberapa catches perlu disarangkan ...
catch :foo do
catch :bar do
do_something_that_can_throw_foo_or_bar
end
end
Telanjang rescuesetara dengan rescue StandardErrordan merupakan konstruksi idiomatis. "Telanjang catch", seperti catch() {throw :foo}, tidak akan pernah menangkap apa pun dan tidak boleh digunakan.
gotodi C / C ++ seperti @docwhat telah disebutkan, Java telah memberi label break dan continue . (Python juga memiliki proposal yang ditolak untuk ini.)