Dari apa yang bisa saya lihat, ada dua bentuk pengelolaan sumber daya: perusakan deterministik dan eksplisit. Contoh dari yang pertama adalah destruktor C ++ dan pointer pintar atau sub DESTROY Perl, sementara contoh yang terakhir akan menjadi paradigma blok-untuk-mengelola-sumber daya Ruby atau antarmuka IDispose .NET.
Bahasa-bahasa yang lebih baru tampaknya memilih yang terakhir, mungkin sebagai efek samping dari penggunaan sistem pengumpulan sampah dari varietas non-referensi penghitungan.
Pertanyaan saya adalah ini: mengingat bahwa penghancur untuk penunjuk cerdas atau sistem pengumpulan sampah penghitungan referensi - hampir menjadi hal yang sama - memungkinkan perusakan sumber daya yang implisit dan transparan, apakah ini merupakan abstraksi yang kurang bocor daripada jenis non-deterministik yang mengandalkan eksplisit notasi?
Saya akan memberikan contoh nyata. Jika Anda memiliki tiga subclass C ++ dari superclass tunggal, satu mungkin memiliki implementasi yang tidak memerlukan penghancuran khusus. Mungkin itu melakukan sihirnya dengan cara lain. Fakta bahwa itu tidak memerlukan penghancuran khusus tidak relevan - semua subclass masih digunakan dengan cara yang sama.
Contoh lain menggunakan blok Ruby. Dua subclass perlu membebaskan sumber daya, sehingga superclass memilih antarmuka yang menggunakan blok di konstruktor, meskipun subclass spesifik lainnya mungkin tidak memerlukannya karena mereka tidak memerlukan penghancuran khusus.
Apakah ini kasus yang terakhir bocor detail implementasi perusakan sumber daya, sedangkan yang pertama tidak?
EDIT: Membandingkan, katakanlah, Ruby ke Perl mungkin lebih adil karena satu memiliki kehancuran deterministik dan yang lainnya belum, namun keduanya sama-sama mengumpulkan sampah.
sumber
(*ptr).Message()
atau yang setaraptr->Message()
. Ada seperangkat ekspresi diizinkan yang tak terbatas, seperti((*ptr))->Message
juga yang setara. Tapi mereka semua bermuara padaexpressionIdentifyingAnObject.Message()
Jawaban:
Teladan Anda sendiri menjawab pertanyaan itu. Penghancuran transparan jelas kurang bocor daripada penghancuran eksplisit. Itu bisa bocor, tapi kurang bocor.
Penghancuran eksplisit analog dengan malloc / gratis di C dengan semua jebakan. Mungkin dengan sedikit gula sintaksis untuk membuatnya tampak berdasarkan lingkup.
Beberapa manfaat dari penghancuran transparan lebih eksplisit: -
pola penggunaan yang sama - Anda
tidak bisa lupa untuk melepaskan sumber daya.
- detail bersihkan jangan membuang sampah lanskap pada titik penggunaan.
sumber
Kegagalan dalam abstraksi sebenarnya bukan fakta bahwa pengumpulan sampah adalah non-deterministik, melainkan pada gagasan bahwa objek "tertarik" pada hal-hal yang mereka pegang referensi, dan tidak tertarik pada hal-hal yang tidak mereka pegang. referensi. Untuk melihat alasannya, pertimbangkan skenario dari sebuah objek yang mempertahankan counter seberapa sering kontrol tertentu dicat. Pada saat pembuatan, ia berlangganan acara "cat" kontrol, dan saat pembuangannya berhenti berlangganan. Acara cukup klik increment lapangan, dan metode
getTotalClicks()
mengembalikan nilai bidang itu.Ketika objek penghitung dibuat, itu harus menyebabkan referensi untuk dirinya sendiri disimpan dalam kontrol yang dimonitor. Kontrol benar-benar tidak peduli tentang objek penghitung, dan akan sama bahagia jika objek penghitung, dan referensi untuk itu, tidak ada lagi, tetapi selama referensi itu ada, ia akan memanggil pengendali acara objek itu setiap kali cat itu sendiri. Tindakan ini sama sekali tidak berguna bagi kontrol, tetapi akan bermanfaat bagi siapa saja yang akan memanggil
getTotalClicks()
objek tersebut.Jika misalnya suatu metode adalah untuk membuat objek "penghitung cat" baru, melakukan beberapa tindakan pada kontrol, mengamati berapa kali kontrol dicat ulang, dan kemudian meninggalkan objek penghitung cat, objek akan tetap berlangganan acara bahkan meskipun tidak ada yang akan peduli jika objek dan semua referensi tentang itu menghilang begitu saja. Objek tidak akan memenuhi syarat untuk koleksi, namun, sampai kontrol itu sendiri. Jika metode itu adalah salah satu yang akan dipanggil ribuan kali dalam masa kendali [skenario yang masuk akal], itu dapat menyebabkan memori meluap tetapi untuk fakta bahwa biaya doa N kemungkinan akan menjadi O (N ^ 2) atau O (N ^ 3) kecuali pemrosesan berlangganan sangat efisien dan sebagian besar operasi sebenarnya tidak melibatkan pengecatan.
Skenario khusus ini dapat ditangani dengan memberikan kontrol menjaga referensi yang lemah ke objek counter daripada yang kuat. Model langganan yang lemah sangat membantu, tetapi tidak berfungsi dalam kasus umum. Misalkan alih-alih ingin memiliki objek yang memantau satu jenis peristiwa dari kontrol tunggal, seseorang ingin memiliki objek event-logger yang memantau beberapa kontrol, dan mekanisme penanganan peristiwa sistem sedemikian rupa sehingga setiap kontrol membutuhkan referensi ke objek event-logger yang berbeda. Dalam hal itu, objek yang menghubungkan kontrol ke event logger harus tetap hidup hanya selama keduanyakontrol dimonitor dan event logger tetap bermanfaat. Jika kontrol maupun pencatat peristiwa tidak memiliki referensi kuat ke acara penautan, itu tidak akan ada meskipun itu masih "berguna". Jika salah satu dari mereka memegang acara yang kuat, masa hidup dari objek yang terhubung mungkin akan sia-sia diperpanjang bahkan jika yang lain mati.
Jika tidak ada referensi ke objek di mana pun di alam semesta, objek tersebut dapat dengan aman dianggap tidak berguna dan dihilangkan dari keberadaan. Fakta bahwa referensi ada pada suatu objek, tidak berarti bahwa objek itu "berguna". Dalam banyak kasus, kegunaan sebenarnya dari objek akan tergantung pada keberadaan referensi ke objek lain yang - dari perspektif GC - sama sekali tidak terkait dengan mereka.
Jika objek secara deterministik diberitahu ketika tidak ada orang yang tertarik pada mereka, mereka akan dapat menggunakan informasi itu untuk memastikan bahwa siapa pun yang akan mendapat manfaat dari pengetahuan itu diberi informasi. Namun, dengan tidak adanya pemberitahuan semacam itu, tidak ada cara umum untuk menentukan objek apa yang dianggap "berguna" jika seseorang hanya mengetahui set referensi yang ada, dan bukan makna semantik yang melekat pada referensi tersebut. Dengan demikian, setiap model yang mengasumsikan bahwa keberadaan atau tidak adanya referensi cukup untuk manajemen sumber daya otomatis akan hancur bahkan jika GC dapat langsung mendeteksi pengabaian objek.
sumber
Tidak ada "destructor, atau antarmuka lain yang mengatakan" kelas ini harus dihancurkan "adalah kontrak dari antarmuka itu. Jika Anda membuat subtipe yang tidak memerlukan penghancuran khusus, saya akan cenderung menganggap bahwa pelanggaran terhadap Prinsip Substitusi Liskov .
Sedangkan untuk C ++ vs. yang lain, tidak ada banyak perbedaan. C ++ memaksa antarmuka itu pada semua objek itu. Abstraksi tidak bisa bocor ketika diminta oleh bahasa.
sumber
DerivedFooThatRequiresSpecialDestruction
hanya dapat dibuat oleh kode yang memanggilnew DerivedFooThatRequiresSpecialDestruction()
. Di sisi lain, metode pabrik yang mengembalikanDerivedFooThatRequiresSpecialDestruction
kode ke yang tidak mengharapkan sesuatu yang memerlukan penghancuran, akan menjadi pelanggaran LSP.Harus memperhatikan siklus dengan tangan bukanlah implisit atau transparan. Satu-satunya pengecualian adalah sistem penghitungan referensi dengan bahasa yang melarang siklus dengan desain. Erlang mungkin merupakan contoh dari sistem seperti itu.
Jadi keduanya mendekati kebocoran. Perbedaan utama adalah bahwa destruktor bocor di mana-mana di C ++ tetapi
IDispose
sangat jarang terjadi pada .NET.sumber