Apakah kelas bersarang di bawah nilai?

9

Saya tidak mencoba untuk mengatakan saya tahu sesuatu yang tidak diketahui orang lain, tetapi saya telah memecahkan lebih banyak desain dengan menggunakan kelas bersarang, jadi saya ingin tahu bagaimana dapat diterima menggunakan ini tampaknya jarang digunakan mekanisme desain.

Ini mengarahkan saya ke pertanyaan: apakah saya akan menempuh jalan yang buruk karena alasan yang akan saya temukan ketika mereka kembali menggigit saya, atau apakah kelas-kelas bersarang mungkin sesuatu yang diremehkan?

Berikut adalah dua contoh yang baru saja saya gunakan untuk: https://gist.github.com/3975581 - yang pertama membantu saya tetap merilis benda-benda pusaka dengan erat, yang kedua izinkan saya memberi akses ke anggota yang dilindungi untuk pekerja ...

Aaron Anodide
sumber
Saya hanya ingin mengucapkan terima kasih atas jawaban / wawasan - Saya tidak yakin bagaimana memilih jawaban jadi saya akan meninggalkannya sementara saya merenungkan saran yang saya dapatkan dan mengunjungi kembali ...
Aaron Anodide

Jawaban:

6

Saya tidak akan menyebut ini "mekanisme desain yang jarang digunakan" - setidaknya, tidak secara universal: meskipun ada toko-toko di mana beberapa kontributor mungkin tidak suka menggunakan kelas bersarang, ini bukan fitur yang tidak jelas sama sekali.

Meskipun keberadaan kelas dengan visibilitas perakitan dan pengenalan lambdas telah secara signifikan mengurangi kebutuhan kelas bersarang * , mereka tetap menjadi pilihan desain yang valid. Meskipun ada beberapa tumpang tindih dengan kelas internal di dalam namespace, fitur kelas bersarang adalah unik dalam membiarkan Anda menyembunyikan kelas sepenuhnya di dalam kelas lain.


* Penggunaan fitur serupa di Jawa jauh lebih tinggi, karena alternatif lain yang tersedia di C # tidak ada di Jawa.

dasblinkenlight
sumber
Jadi apakah baik menyembunyikan kelas sepenuhnya di kelas lain sesuai esensi dari desain OOP?
Maxood
1
@ Maxood Ada baiknya menyembunyikan kelas jika Anda bisa menyembunyikannya. Pengguna API Anda harus tahu sesedikit mungkin tentang cara API Anda diimplementasikan.
dasblinkenlight
3

Pertimbangkan sejenak bahwa Anda menulis kelas di dalam kelas lain, yang tidak akan pernah digunakan di tempat lain di program Anda. Karena jika Anda menggunakannya di tempat lain, Anda akan menjadikannya kelas publik biasa, seperti yang lainnya.

Jadi hal yang seharusnya membuat OOP hebat (dapat digunakan kembali) tidak ada di sini. Selain itu, apa yang bisa Anda capai dengan kelas bersarang yang tidak dapat Anda capai dengan metode biasa dan anggota pribadi dalam kelas induk?

Untuk pola perangkat lunak yang bermanfaat menggunakan kelas bersarang, lihat di sini .

Robert Harvey
sumber
10
Saya tidak pernah membeli barang reusability, setidaknya tidak seperti biasanya. (1) Memanggil kode / kelas yang ada (yang tampaknya Anda bicarakan, dan yang biasanya saya lihat sebagai definisi penggunaan kembali) sama sekali tidak ada hubungannya dengan OOP, itu hanya modularitas dasar. (2) Subtipe polimorfisme, yang merupakan salah satu ciri khas OOP, memungkinkan penggunaan kembali kode klien dengan membuat implementasi spesifik tidak relevan , yaitu bekerja persis dengan cara yang sama apakah kelas beton dapat diakses atau tidak. TKI itu reuse yang saya beli, tetapi ia bekerja dengan kelas bersarang juga.
1
Saya akan mengatakan ada juga isolasi namespace yang diberikan oleh kelas induk - jadi jika Anda ingin, kedua kelas A dan B bisa bersarang kelas "Params", dan akses ke anggota non-publik dari kelas yang mengandung. Bukankah keduanya alasan untuk memiliki kelas batin yang digunakan di luar kelas?
Aaron Anodide
@AaronAnodide Itu seharusnya menjadi jawaban tentang cara yang baik untuk menggunakan kelas bersarang. Persis bagaimana / mengapa saya menggunakannya, ada baiknya mengatur kode.
Izkata
2

am I going down an inherintly bad path

Saya pikir dalam contoh kedua Anda (subclass pekerja) Anda pasti. Anda telah memetakan setiap subclass ke status tertentu di kelas super. Jadi sekarang setiap kali Anda ingin menambahkan negara ke kelas super Anda perlu membuat perubahan di tiga lokasi (tambahkan negara ke kelas super, tambahkan sub kelas baru, dan ubah konstruktor kelas turunan untuk menambahkan sub kelas ke daftar ).

Penggunaan kelas bersarang untuk mengakses anggota pribadi tampaknya merupakan penggunaan yang valid (saya belum pernah melakukannya secara pribadi) tetapi kasus khusus Anda tidak berfungsi di sini.

Adapun contoh bagian tubuh. Karena semua kelas bersarang bersifat publik, Anda tidak benar-benar melakukan banyak hal kecuali penempatan nama. Jika kelas-kelas ini tumbuh untuk memasukkan lebih banyak fungsi, Anda mungkin hanya menemukan bahwa kelas-kelas bersarang hanya mengacaukan antarmuka dan Anda menyaring kode untuk menemukan sesuatu yang spesifik. Saya juga memperhatikan bahwa karena Anda memiliki kelas bersarang Anda terpaksa melanggar konvensi penamaan dan memberi nama kelas Anda dengan huruf kecil (mungkin ini pilihan). Tetapi argumen-argumen ini lebih dangkal daripada yang sebenarnya salah.

Kecuali, tentu saja, Anda perlu menerapkan lengan tanpa tubuh. Maka menciptakan lengan dengan melakukan hal berikut ini membingungkan karena tidak ada tubuh / batang / sisi. (Perhatikan juga casing yang membingungkan).

arm newArm = new Body.torso.side.arm("");
nickles80
sumber
1

Satu-satunya keuntungan yang saya dapat pikirkan tentang kelas bersarang adalah mereka dapat dibuat privat (atau dilindungi). Saya akan mengatakan dalam hal ini kelas bertingkat dapat membantu Anda merangkum fungsionalitas jika kelas dimaksudkan untuk digunakan oleh kelas luar dan kelas itu saja.

Bok McDonagh
sumber
1

Dalam pengalaman saya, kelas bersarang

  • Kembali untuk menghantuiku
  • Telah digunakan ketika saya ingin memotong sudut
  • Membuat pengujian mimpi buruk
  • Memiliki dampak negatif pada pemisahan masalah dan desain keseluruhan

Telah melihat sekilas kelas Anda, dan segera saya pikir itu:

  • Sangat menyakitkan untuk melihatnya karena kelasnya sangat besar
  • Saya tidak bisa menguji "jari" tanpa cukup banyak membuat seluruh tubuh
  • Saya tidak dapat memiliki beberapa implementasi batang tubuh. Tampaknya tidak begitu jelas dalam konteks "tubuh manusia", tetapi dalam skenario yang berbeda ini akan menjadi jelas.

Mengapa tidak memisahkan kelas Anda menjadi beberapa kelas dan memberi mereka ruang nama yang terpisah. Misalnya

WindowsGame1.PhysicalModel.UpperBody
WindowsGame1.PhysicalModel.LowerBody
WindowsGame1.PhysicalModel.UpperBody.Arms
CodeART
sumber