Dalam posting blog Kathleen Dollard tahun 2008 , dia menyajikan alasan menarik untuk menggunakan kelas bersarang di .net. Namun, dia juga menyebutkan bahwa FxCop tidak menyukai kelas bersarang. Saya berasumsi bahwa orang yang menulis aturan FxCop tidak bodoh, jadi pasti ada alasan di balik posisi itu, tetapi saya belum dapat menemukannya.
93
Jawaban:
Gunakan kelas bertingkat jika kelas yang Anda susun hanya berguna untuk kelas yang melingkupi. Misalnya, kelas bertingkat memungkinkan Anda menulis sesuatu seperti (disederhanakan):
Anda dapat membuat definisi lengkap tentang kelas Anda di satu tempat, Anda tidak perlu melewati rintangan PIMPL apa pun untuk menentukan cara kerja kelas Anda, dan dunia luar tidak perlu melihat apa pun dari penerapan Anda.
Jika kelas TreeNode adalah eksternal, Anda harus membuat semua bidang
public
atau membuat banyakget/set
metode untuk menggunakannya. Dunia luar akan memiliki kelas lain yang mencemari akal sehat mereka.sumber
Dari Tutorial Java Sun:
Mengapa Menggunakan Kelas Bersarang? Ada beberapa alasan kuat untuk menggunakan kelas bersarang, di antaranya:
Pengelompokan kelas secara logis — Jika sebuah kelas hanya berguna untuk satu kelas lain, maka logis untuk menyematkannya di kelas tersebut dan menjaga keduanya bersama-sama. Menyusun "kelas pembantu" seperti itu membuat paket mereka lebih efisien.
Enkapsulasi yang ditingkatkan — Pertimbangkan dua kelas tingkat atas, A dan B, di mana B memerlukan akses ke anggota A yang dinyatakan sebagai pribadi. Dengan menyembunyikan kelas B di dalam kelas A, anggota A dapat dinyatakan sebagai pribadi dan B dapat mengaksesnya. Selain itu, B sendiri bisa disembunyikan dari dunia luar.<- Ini tidak berlaku untuk implementasi C # kelas bersarang, ini hanya berlaku untuk Java.Kode yang lebih mudah dibaca dan dapat dipelihara — Menyusun kelas kecil dalam kelas tingkat atas akan menempatkan kode lebih dekat ke tempatnya digunakan.
sumber
Pola tunggal yang sepenuhnya Malas dan aman untuk benang
sumber: http://www.yoda.arachsys.com/csharp/singleton.html
sumber
Itu tergantung pada penggunaannya. Saya jarang akan menggunakan kelas bersarang Publik tetapi menggunakan kelas bersarang Pribadi sepanjang waktu. Kelas bertingkat privat bisa digunakan untuk sub-objek yang dimaksudkan untuk digunakan hanya di dalam induk. Contohnya adalah jika kelas HashTable berisi objek Entri pribadi untuk menyimpan data hanya secara internal.
Jika kelas dimaksudkan untuk digunakan oleh pemanggil (secara eksternal), saya biasanya suka membuatnya menjadi kelas mandiri yang terpisah.
sumber
Selain alasan lain yang tercantum di atas, ada satu alasan lagi yang dapat saya pikirkan tidak hanya untuk menggunakan kelas bersarang, tetapi pada kenyataannya kelas bersarang publik. Bagi mereka yang bekerja dengan beberapa kelas generik yang berbagi parameter tipe generik yang sama, kemampuan untuk mendeklarasikan namespace generik akan sangat berguna. Sayangnya, .Net (atau setidaknya C #) tidak mendukung gagasan ruang nama generik. Jadi untuk mencapai tujuan yang sama, kita dapat menggunakan kelas generik untuk memenuhi tujuan yang sama. Ambil contoh kelas berikut yang terkait dengan entitas logis:
Kita dapat menyederhanakan tanda tangan dari kelas-kelas ini dengan menggunakan namespace generik (diimplementasikan melalui kelas-kelas bersarang):
Kemudian, melalui penggunaan kelas parsial seperti yang disarankan oleh Erik van Brakel dalam komentar sebelumnya, Anda dapat memisahkan kelas menjadi file bersarang yang terpisah. Saya merekomendasikan menggunakan ekstensi Visual Studio seperti NestIn untuk mendukung penumpukan file kelas parsial. Hal ini memungkinkan file kelas "namespace" juga digunakan untuk mengatur file kelas bersarang dalam folder seperti cara.
Sebagai contoh:
Entity.cs
Entity.BaseDataObject.cs
Entity.BaseDataObjectList.cs
Entity.IBaseBusiness.cs
Entity.IBaseDataAccess.cs
File di penjelajah solusi studio visual kemudian akan diatur sebagai berikut:
Dan Anda akan menerapkan namespace generik seperti berikut:
User.cs
User.DataObject.cs
User.DataObjectList.cs
User.IBusiness.cs
User.IDataAccess.cs
Dan file akan diatur dalam penjelajah solusi sebagai berikut:
Di atas adalah contoh sederhana menggunakan kelas luar sebagai namespace generik. Saya telah membangun "ruang nama umum" yang berisi 9 atau lebih parameter tipe di masa lalu. Harus menjaga agar parameter jenis tersebut tetap tersinkronisasi di sembilan jenis yang semuanya diperlukan untuk mengetahui parameter jenis itu membosankan, terutama saat menambahkan parameter baru. Penggunaan namespace generik membuat kode itu jauh lebih mudah diatur dan dibaca.
sumber
Jika saya memahami artikel Katheleen dengan benar, dia mengusulkan untuk menggunakan kelas bertingkat agar dapat menulis SomeEntity.Collection daripada EntityCollection <SomeEntity>. Menurut saya ini cara kontroversial untuk menghemat beberapa pengetikan. Saya cukup yakin bahwa dalam koleksi aplikasi dunia nyata akan memiliki beberapa perbedaan dalam implementasi, jadi Anda tetap perlu membuat kelas terpisah. Menurut saya, menggunakan nama kelas untuk membatasi ruang lingkup kelas lainnya bukanlah ide yang baik. Ini mencemari intellisense dan memperkuat ketergantungan antar kelas. Menggunakan ruang nama adalah cara standar untuk mengontrol ruang lingkup kelas. Namun saya menemukan bahwa penggunaan kelas bersarang seperti di komentar @hazzen dapat diterima kecuali Anda memiliki banyak kelas bersarang yang merupakan tanda desain yang buruk.
sumber
Saya sering menggunakan kelas bersarang untuk menyembunyikan detail implementasi. Contoh dari jawaban Eric Lippert di sini:
Pola ini menjadi lebih baik dengan penggunaan obat generik. Lihat pertanyaan ini untuk dua contoh keren. Jadi saya akhirnya menulis
dari pada
Saya juga dapat memiliki daftar umum
Equality<Person>
tetapi tidakEqualityComparer<Person, int>
dimana
itu tidak mungkin. Itulah keuntungan dari kelas bersarang yang diturunkan dari kelas induk.
Kasus lain (dengan sifat yang sama - menyembunyikan implementasi) adalah ketika Anda ingin membuat anggota kelas (bidang, properti, dll.) Hanya dapat diakses untuk satu kelas:
sumber
Penggunaan lain yang belum disebutkan untuk kelas bersarang adalah segregasi tipe generik. Misalnya, seseorang ingin memiliki beberapa keluarga generik kelas statis yang dapat menggunakan metode dengan berbagai jumlah parameter, bersama dengan nilai untuk beberapa parameter tersebut, dan menghasilkan delegasi dengan lebih sedikit parameter. Misalnya, seseorang ingin memiliki metode statis yang dapat mengambil
Action<string, int, double>
dan menghasilkan aString<string, int>
yang akan memanggil tindakan yang diberikan lewat 3.5 sebagaidouble
; seseorang mungkin juga ingin memiliki metode statis yang dapat mengambilAction<string, int, double>
dan menghasilkanAction<string>
, lewat7
sebagaiint
dan5.3
sebagaidouble
. Menggunakan kelas bertingkat generik, seseorang dapat mengatur agar pemanggilan metode menjadi seperti:atau, karena tipe terakhir di setiap ekspresi dapat disimpulkan meskipun ekspresi sebelumnya tidak dapat:
Menggunakan tipe generik bersarang memungkinkan untuk mengetahui delegasi mana yang berlaku untuk bagian mana dari keseluruhan deskripsi tipe.
sumber
Kelas bersarang dapat digunakan untuk kebutuhan berikut:
sumber
Seperti yang disebutkan nawfal implementasi pola Pabrik Abstrak, kode tersebut dapat diperluas untuk mencapai pola Class Clusters yang didasarkan pada pola Pabrik Abstrak.
sumber
Saya suka mengelompokkan pengecualian yang unik untuk satu kelas, yaitu. yang tidak pernah terlempar dari tempat lain.
Sebagai contoh:
Ini membantu menjaga file proyek Anda tetap rapi dan tidak penuh dengan seratus kelas pengecualian kecil yang gemuk.
sumber
Ingatlah bahwa Anda harus menguji kelas bertingkat. Jika bersifat pribadi, Anda tidak akan dapat mengujinya secara terpisah.
Anda bisa membuatnya internal, sehubungan dengan
InternalsVisibleTo
atributnya . Namun, ini akan sama dengan membuat bidang pribadi internal hanya untuk tujuan pengujian, yang saya anggap sebagai dokumentasi diri yang buruk.Jadi, Anda mungkin hanya ingin mengimplementasikan kelas bertingkat privat yang melibatkan kompleksitas rendah.
sumber
ya untuk kasus ini:
sumber
Berdasarkan pemahaman saya tentang konsep ini, kita dapat menggunakan fitur ini ketika kelas terkait satu sama lain secara konseptual. Maksud saya beberapa dari mereka adalah satu Item lengkap dalam bisnis kami seperti entitas yang ada di dunia DDD yang membantu objek akar agregat untuk melengkapi logika bisnisnya.
Untuk memperjelas, saya akan menunjukkan ini melalui contoh:
Bayangkan kita memiliki dua kelas seperti Order dan OrderItem. Di kelas pesanan, kami akan mengelola semua orderItems dan di OrderItem kami menyimpan data tentang satu pesanan untuk klarifikasi, Anda dapat melihat kelas di bawah ini:
sumber