Bunu bir soru olarak gönderdiğine sevindim. :)
Yıkıcıların ve finally
kavramsal olarak farklı olduklarını söylemeye çalışıyordum :
- Yıkıcılar kaynakları serbest bırakmak içindir ( veri )
finally
arayan kişiye geri dönmek içindir ( kontrol )
Diyelim ki, bu varsayımsal sözde kodu:
try {
bar();
} finally {
logfile.print("bar has exited...");
}
finally
burada kaynak yönetimi problemi değil, tamamen kontrol problemi çözülüyor.
Bunu çeşitli nedenlerden dolayı bir yıkıcıda yapmak mantıklı olmaz:
- Hiçbir şey "edinilmiş" veya "yaratılmış" değildir
- Günlük dosyasına yazdırmak için Başarısızlık olacak değil kaynak sızıntıları, veri bozulması, vb (burada günlük dosyası başka yerde programa geri beslenir olmadığını varsayarak) neden
- Yıkmak meşru
logfile.print
, oysa yıkım (kavramsal olarak) başarısız olamaz
İşte bu sefer Javascript'teki gibi başka bir örnek:
var mo_document = document, mo;
function observe(mutations) {
mo.disconnect(); // stop observing changes to prevent re-entrance
try {
/* modify stuff */
} finally {
mo.observe(mo_document); // continue observing (conceptually, this can fail)
}
}
mo = new MutationObserver(observe);
return observe();
Yukarıdaki örnekte, yine, serbest bırakılacak kaynak yoktur.
Aslında, finally
blok edilir edinme hedefine, potansiyel olarak başarısız olabilir ulaşmak için dahili olarak kaynakları. Bu nedenle, bir yıkıcı kullanmak mantıklı değildir (Javascript'te bir tane varsa).
Öte yandan, bu örnekte:
b = get_data();
try {
a.write(b);
} finally {
free(b);
}
finally
bir kaynağı yok ediyor b
. Bu bir veri sorunu. Sorun, kontrolü arayana temiz bir şekilde geri döndürmek değil, kaynak sızıntılarından kaçınmaktır.
Başarısızlık bir seçenek değildir ve (kavramsal olarak) asla meydana gelmemelidir.
Her sürümü b
mutlaka bir satın alma işlemiyle eşleştirilir ve RAII kullanmak mantıklıdır.
Başka bir deyişle, ya ikisinin de aynı sorun olduğu anlamına gelmediği ya da her ikisinin de her ikisi için de uygun çözümler olduğu ya ikisini de simüle etmek için kullanabilmenizdir.