Ya, ensure
memastikan bahwa kode selalu dievaluasi. Itu sebabnya disebut ensure
. Jadi, itu setara dengan Java dan C # finally
.
Aliran umum dari begin
/ rescue
/ else
/ ensure
/ end
terlihat seperti ini:
begin
# something which might raise an exception
rescue SomeExceptionClass => some_variable
# code that deals with some exception
rescue SomeOtherException => some_other_variable
# code that deals with some other exception
else
# code that runs only if *no* exception was raised
ensure
# ensure that this code always runs, no matter what
# does not change the final value of the block
end
Anda bisa keluar rescue
, ensure
atau else
. Anda juga dapat mengabaikan variabel dalam hal ini Anda tidak akan dapat memeriksa pengecualian dalam kode penanganan pengecualian Anda. (Ya, Anda selalu dapat menggunakan variabel pengecualian global untuk mengakses pengecualian terakhir yang dimunculkan, tapi itu sedikit gila.) Dan Anda dapat meninggalkan kelas pengecualian, dalam hal ini semua pengecualian yang mewarisi dari StandardError
akan ditangkap. (Harap dicatat bahwa ini tidak berarti bahwa semua pengecualian tertangkap, karena ada pengecualian yang contoh Exception
tapi tidak StandardError
. Pengecualian Kebanyakan sangat parah bahwa kompromi integritas program seperti SystemStackError
, NoMemoryError
, SecurityError
, NotImplementedError
, LoadError
, SyntaxError
, ScriptError
, Interrupt
,SignalException
atau SystemExit
.)
Beberapa blok membentuk blok pengecualian implisit. Sebagai contoh, definisi metode secara implisit juga merupakan blok pengecualian, jadi alih-alih menulis
def foo
begin
# ...
rescue
# ...
end
end
Anda hanya menulis
def foo
# ...
rescue
# ...
end
atau
def foo
# ...
ensure
# ...
end
Hal yang sama berlaku untuk class
definisi dan module
definisi.
Namun, dalam kasus spesifik yang Anda tanyakan, sebenarnya ada ungkapan yang jauh lebih baik. Secara umum, ketika Anda bekerja dengan beberapa sumber daya yang Anda perlu bersihkan pada akhirnya, Anda melakukannya dengan melewati blok ke metode yang melakukan semua pembersihan untuk Anda. Ini mirip dengan using
blok di C #, kecuali bahwa Ruby sebenarnya cukup kuat sehingga Anda tidak perlu menunggu imam besar Microsoft turun dari gunung dan dengan ramah mengubah kompiler mereka untuk Anda. Di Ruby, Anda bisa menerapkannya sendiri:
# This is what you want to do:
File.open('myFile.txt', 'w') do |file|
file.puts content
end
# And this is how you might implement it:
def File.open(filename, mode='r', perm=nil, opt=nil)
yield filehandle = new(filename, mode, perm, opt)
ensure
filehandle&.close
end
Dan apa yang Anda ketahui: ini sudah tersedia di perpustakaan inti sebagai File.open
. Tetapi ini adalah pola umum yang dapat Anda gunakan dalam kode Anda sendiri, untuk menerapkan segala jenis pembersihan sumber daya (à la using
dalam C #) atau transaksi atau apa pun yang mungkin Anda pikirkan.
Satu-satunya kasus di mana ini tidak berhasil, jika memperoleh dan melepaskan sumber daya didistribusikan di berbagai bagian program. Tetapi jika dilokalkan, seperti dalam contoh Anda, maka Anda dapat dengan mudah menggunakan blok sumber daya ini.
BTW: di C # modern, using
sebenarnya berlebihan, karena Anda dapat mengimplementasikan blok sumber daya gaya-Ruby sendiri:
class File
{
static T open<T>(string filename, string mode, Func<File, T> block)
{
var handle = new File(filename, mode);
try
{
return block(handle);
}
finally
{
handle.Dispose();
}
}
}
// Usage:
File.open("myFile.txt", "w", (file) =>
{
file.WriteLine(contents);
});
begin
blok.