Anlaşılan tahmin ettiğiniz gibi, evet, C ++ bu mekanizma olmadan aynı yetenekleri sunar. Bu nedenle, kesinlikle konuşursak, try
/ finally
mekanizma gerçekten gerekli değildir.
Bununla birlikte, onsuz yapmak dilin geri kalanının nasıl tasarlandığına dair bazı zorunluluklar getirdiğini söyledi. C ++ 'da aynı eylemler bir sınıf yıkıcısına dahil edilmiştir. Bu öncelikle (sadece?) İşe yarıyor, çünkü C ++ 'daki yıkıcı çağırma deterministik. Bu da, bazıları kesinlikle sezgisel olmayan nesnelerin yaşamları hakkında oldukça karmaşık kurallara yol açıyor.
Diğer dillerin çoğu bunun yerine bir tür çöp toplama biçimi sağlar. Çöp toplama ile ilgili tartışmalı şeyler olsa da (örneğin, diğer bellek yönetimi yöntemlerine göre etkinliği) bir şey genellikle değildir: bir nesnenin doğrudan çöp toplayıcı tarafından "temizleneceği" zaman tam olarak bağlı değildir nesnenin kapsamına. Bu, temizleme işleminin ya doğru işlem için basit bir şekilde yapılması gerektiğinde belirleyici olması gerektiğinde veya temizleme işlemlerinin keyfi olarak ertelenmeyeceği kadar değerli kaynaklarla uğraşırken kullanımını engeller. try
/ finally
bu dillerin bu deterministik temizliği gerektiren durumlarla başa çıkmalarını sağlar.
Sanırım bu yetenek için C ++ sözdiziminin Java'nınkinden daha az "dost" olduğunu iddia edenlerin bu noktayı kaçırdıklarını düşünüyorum. Daha da kötüsü, sözdiziminin çok ötesine geçen sorumluluk dağılımı konusunda çok daha önemli bir noktayı kaçırıyorlar ve kodun nasıl tasarlandığı ile daha çok ilgisi var.
C ++ 'da, bu deterministik temizleme, nesnenin yıkıcısında gerçekleşir. Bu, nesnenin kendisinden sonra temizlemek için tasarlanabileceği (ve normal olarak tasarlanması gerektiği) anlamına gelir. Bu, nesneye yönelik tasarımın özüne gider - bir soyutlama sağlamak ve kendi değişmezlerini uygulamak için bir sınıf tasarlanmalıdır. C ++ 'da, kişi tam olarak bunu yapar - ve sağladığı değişmezlerden biri, nesne tahrip edildiğinde, o nesne tarafından kontrol edilen kaynakların (hepsi sadece hafıza değil) doğru şekilde imha edileceğidir.
Java (ve benzeri) biraz farklıdır. finalize
Teorik olarak benzer yetenekler sağlayabilecek bir şeye destek verirlerse de , destek o kadar zayıftır ki, temelde kullanılamaz (ve aslında, hiç kullanılmamış).
Sonuç olarak, sınıfın kendisi gerekli temizliği yapabilmek yerine, sınıfın müşterisinin bunu yapmak için adımlar atması gerekir. Eğer yeterince kısa görüşlü bir karşılaştırma yaparsak, ilk bakışta bu farkın oldukça küçük olduğu ve Java'nın bu konuda C ++ ile oldukça rekabetçi olduğu anlaşılabilir. Bunun gibi bir şeyle sonuçlanır. C ++ 'da sınıf şöyle görünür:
class Foo {
// ...
public:
void do_whatever() { if (xyz) throw something; }
~Foo() { /* handle cleanup */ }
};
... müşteri kodu şöyle görünür:
void f() {
Foo f;
f.do_whatever();
// possibly more code that might throw here
}
Java'da nesnenin sınıfta biraz daha az kullanıldığı yerlerde biraz daha fazla kod paylaşıyoruz. Bu başlangıçta oldukça eşit bir takas gibi görünüyor. Gerçekte, en tipik kodda sadece sınıfı tanımlamak, çünkü uzak olsa ondan var bir yerde, ama biz kullanmak o birçok yerde. C ++ yaklaşımı, temizliği tek bir yerde ele almak için bu kodu yazdığımız anlamına gelir. Java yaklaşımı, temizliği işlemek için birçok kez, birçok yerde - o sınıfın bir nesnesini kullandığımız her yerde bu kodu yazmamız gerektiği anlamına gelir.
Kısacası, Java yaklaşımı temel olarak sağlamaya çalıştığımız birçok soyutlamanın "sızdıran" olduğunu garanti eder - belirleyici temizlik gerektiren her sınıf, sınıfın müşterisine ne temizlemenin ayrıntıları ve temizlemenin nasıl yapılacağı hakkında bilgi sahibi olmasını zorunlu kılar. , bu detayların sınıfta gizli kalması yerine.
Yukarıda "Java yaklaşımı" olarak adlandırdığım halde, try
/ finally
ve diğer isimler altındaki benzer mekanizmalar tamamen Java ile sınırlı değildir. Öne çıkan bir örnek için, .NET dillerinin çoğu (tümü?) (Örneğin, C #) aynı şeyi sağlar.
Hem Java hem de C # 'nın en son yinelemeleri, aynı zamanda "klasik" Java ve C ++ arasında bu noktada bir yarım nokta noktası sağlar. C # 'da, temizleme işlemini otomatikleştirmek isteyen bir nesne, (en azından belli belirsiz) bir C ++ yıkıcısına benzer IDisposable
bir Dispose
yöntem sağlayan arayüzü uygulayabilir . Bu , Java'daki bir try
/ finally
like aracılığıyla kullanılabilse de , C # , bir kapsam girilip oluşturulacak ve kapsamdan çıkıldığında yok edilecek kaynakları tanımlamanıza izin veren bir açıklama ile görevi biraz daha otomatik hale getirir using
. Her ne kadar C ++ tarafından sağlanan otomasyon seviyesi ve kesinliği hala yetersiz olsa da, bu yine de Java üzerinde kayda değer bir gelişmedir. Özellikle, sınıf tasarımcısı nasıl detaylarını merkezileştirebilir.Sınıfın uygulanmasında elden çıkarılması IDisposable
. İstemci programcısı için geriye kalan tek using
şey, IDisposable
arayüzün olması gerektiği zaman kullanılacağından emin olmak için bir ifade yazmak için daha az yük . Java 7 ve daha yeni sürümlerinde, suçluyu korumak için adlar değiştirildi, ancak temel fikir temelde aynı.