Pengecualian Ruby
Pengecualian dan pelaksanaan sentiasa dikaitkan bersama. Jika anda membuka fail yang tidak wujud dan tidak mengendalikan situasi dengan sewajarnya, program anda dianggap berkualiti rendah.
Jika pengecualian berlaku, program akan berhenti. Pengecualian digunakan untuk mengendalikan pelbagai jenis ralat yang mungkin berlaku semasa pelaksanaan program, jadi tindakan sewajarnya diambil tanpa menghentikan program sepenuhnya.
Ruby menyediakan mekanisme yang sempurna untuk mengendalikan pengecualian. Kita boleh menyertakan kod yang mungkin membuang pengecualian dalam blok mula/akhir dan menggunakan klausa menyelamat untuk memberitahu Ruby jenis pengecualian yang perlu dikendalikan.
Sintaks
begin #开始 raise.. #抛出异常 rescue [ExceptionType = StandardException] #捕获指定类型的异常 缺省值是StandardException $! #表示异常信息 $@ #表示异常出现的代码位置 else #其余异常 .. ensure #不管有没有异常,进入该代码块 end #结束
Segala-galanya daripada bermula hingga menyelamatkan dilindungi. Jika pengecualian berlaku semasa pelaksanaan blok kod, kawalan diserahkan kepada blok antara menyelamat dan tamat.
Untuk setiap klausa menyelamat dalam blok mula, Ruby membandingkan pengecualian yang dilemparkan dengan setiap hujah secara bergilir-gilir. Jika pengecualian yang dinamakan dalam klausa penyelamat adalah daripada jenis yang sama seperti pengecualian yang dilemparkan pada masa ini, atau merupakan kelas induk pengecualian itu, perlawanan itu berjaya.
Jika pengecualian tidak sepadan dengan semua jenis ralat yang ditentukan, kita boleh menggunakan klausa else selepas semua klausa menyelamat.
Contoh
#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "File opened successfully" end rescue file = STDIN end print file, "==", STDIN, "\n"
Hasil keluaran contoh di atas ialah. Anda boleh melihat bahawa STDIN menggantikan fail kerana gagal membuka .
#<IO:0xb7d16f84>==#<IO:0xb7d16f84>
Gunakan cuba semula pernyataan
Anda boleh menggunakan blok menyelamat untuk menangkap pengecualian dan kemudian gunakan pernyataan cuba semula untuk memulakan pelaksanaan dari awal mula blok.
Syntax
begin # 这段代码抛出的异常将被下面的 rescue 子句捕获 rescue # 这个块将捕获所有类型的异常 retry # 这将把控制移到 begin 的开头 end
Instance
#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "File opened successfully" end rescue fname = "existant_file" retry end
Berikut ialah aliran pemprosesan:
Pengecualian berlaku semasa membuka.
Lompat untuk menyelamatkan. fname ditugaskan semula.
Lompat ke permulaan permulaan melalui cuba semula.
Kali ini fail berjaya dibuka.
Teruskan dengan proses asas.
Nota: Jika fail yang dinamakan semula tidak wujud, kod daya ini akan mencuba tanpa had. Oleh itu, gunakan cuba semula dengan berhati-hati apabila mengendalikan pengecualian.
Menggunakan pernyataan raise
Anda boleh menggunakan pernyataan raise untuk membuang pengecualian. Kaedah berikut membuang pengecualian apabila dipanggil. Mesej kedua akan dikeluarkan.
Syntax
raise 或 raise "Error Message" 或 raise ExceptionType, "Error Message" 或 raise ExceptionType, "Error Message" condition
Borang pertama hanya membuang semula pengecualian semasa (atau RuntimeError jika tiada pengecualian semasa). Ini digunakan dalam pengendali pengecualian yang perlu mentafsir pengecualian sebelum menyerahkannya.
Borang kedua mencipta pengecualian RuntimeError baharu, menetapkan mesejnya kepada rentetan yang diberikan. Pengecualian kemudiannya dilemparkan ke atas timbunan panggilan.
Borang ketiga mencipta pengecualian menggunakan parameter pertama, dan kemudian menetapkan mesej berkaitan sebagai parameter kedua.
Borang keempat adalah serupa dengan borang ketiga, anda boleh menambah sebarang pernyataan bersyarat tambahan (seperti melainkan) untuk membuang pengecualian.
Instance
#!/usr/bin/ruby begin puts 'I am before the raise.' raise 'An error has occurred.' puts 'I am after the raise.' rescue puts 'I am rescued.' end puts 'I am after the begin block.'
Contoh di atas menjalankan hasil output ialah:
I am before the raise. I am rescued. I am after the begin block.
Contoh lain yang menunjukkan penggunaan raise:
#!/usr/bin/ruby begin raise 'A test exception.' rescue Exception => e puts e.message puts e.backtrace.inspect end
di atas Hasil keluaran contoh berjalan ialah:
A test exception. ["main.rb:4"]
Gunakan pernyataan pastikan
Kadangkala, tidak kira sama ada pengecualian dilemparkan, anda perlu memastikan bahawa beberapa pemprosesan selesai pada penghujung blok kod. Sebagai contoh, anda mungkin mempunyai fail terbuka apabila anda masuk, dan apabila anda keluar dari blok, anda perlu memastikan anda menutup fail tersebut.
Klausapastikan melakukan perkara itu. pastikan diletakkan selepas klausa penyelamat terakhir dan mengandungi blok kod yang sentiasa dilaksanakan apabila blok ditamatkan. Tidak kira sama ada blok itu keluar dengan anggun, sama ada ia melontar dan mengendalikan pengecualian, atau sama ada ia ditamatkan dengan pengecualian yang tidak ditangkap, blok pastikan akan sentiasa berjalan.
Sintaks
begin #.. 过程 #.. 抛出异常 rescue #.. 处理错误 ensure #.. 最后确保执行 #.. 这总是会执行 end
Contoh
begin raise 'A test exception.' rescue Exception => e puts e.message puts e.backtrace.inspect ensure puts "Ensuring execution" end
Keluaran contoh di atas ialah:
A test exception. ["main.rb:4"] Ensuring execution
Gunakan pernyataan else
Jika klausa lain disediakan, ia biasanya diletakkan selepas klausa menyelamat dan sebelum mana-mana pastikan. Badan klausa
else hanya dilaksanakan jika badan kod tidak membuang pengecualian.
Sintaks
begin #.. 过程 #.. 抛出异常 rescue #.. 处理错误 else #.. 如果没有异常则执行 ensure #.. 最后确保执行 #.. 这总是会执行 end
Contoh
begin # 抛出 'A test exception.' puts "I'm not raising exception" rescue Exception => e puts e.message puts e.backtrace.inspect else puts "Congratulations-- no errors!" ensure puts "Ensuring execution" end
Keluaran contoh di atas ialah:
I'm not raising exception Congratulations-- no errors! Ensuring execution
Gunakan pembolehubah $! Mekanisme pengecualian
Catch and Throw
raise and rescue boleh menghentikan pelaksanaan apabila ralat berlaku Kadangkala perlu untuk melompat keluar dari beberapa struktur bersarang dalam semasa pemprosesan biasa. Di sinilah tangkapan dan lempar berguna.
catch mentakrifkan blok yang menggunakan nama yang diberikan (yang boleh menjadi Simbol atau Rentetan) sebagai label. Blok akan dilaksanakan seperti biasa sehingga lontaran ditemui.
Sintaks
throw :lablename #.. 这不会被执行 catch :lablename do #.. 在遇到一个 throw 后匹配将被执行的 catch end 或 throw :lablename condition #.. 这不会被执行 catch :lablename do #.. 在遇到一个 throw 后匹配将被执行的 catch end
Contoh
Dalam contoh berikut, jika pengguna menaip '!' sebagai tindak balas kepada sebarang gesaan, lontaran digunakan untuk menamatkan interaksi dengan pengguna .
def promptAndGet(prompt) print prompt res = readline.chomp throw :quitRequested if res == "!" return res end catch :quitRequested do name = promptAndGet("Name: ") age = promptAndGet("Age: ") sex = promptAndGet("Sex: ") # .. # 处理信息 end promptAndGet("Name:")
Program di atas memerlukan interaksi manusia, anda boleh mencubanya pada komputer anda. Hasil keluaran contoh di atas ialah:
Name: Ruby on Rails Age: 3 Sex: ! Name:Just Ruby
Pengecualian Kelas
Kelas dan modul standard Ruby membuang pengecualian. Semua kelas pengecualian membentuk hierarki, termasuk kelas Pengecualian di bahagian atas. Tahap seterusnya ke bawah ialah tujuh jenis yang berbeza:
Interrupt
NoMemoryError
SignalException
ScriptError
StandardError
SystemExit
Fatal adalah satu lagi pengecualian dalam lapisan ini, tetapi penterjemah Ruby hanya menggunakannya secara dalaman.
Kedua-dua ScriptError dan StandardError mempunyai beberapa subkelas, tetapi kami tidak perlu mengetahui butiran tersebut di sini. Perkara yang paling penting ialah mencipta kelas pengecualian kita sendiri, mereka mestilah subkelas kelas Pengecualian atau keturunannya.
Mari kita lihat contoh:
class FileSaveError < StandardError attr_reader :reason def initialize(reason) @reason = reason end end
Sekarang, lihat contoh berikut di mana pengecualian di atas akan digunakan:
File.open(path, "w") do |file| begin # 写出数据 ... rescue # 发生错误 raise FileSaveError.new($!) end end
Di sini, baris yang paling penting ialah naikkan FileSaveError.new($!). Kami memanggil kenaikan untuk menunjukkan bahawa pengecualian telah berlaku, menyerahkannya kepada contoh baharu FileSaveError yang gagal menulis data disebabkan pengecualian khusus.