Bagaimana merancang untuk warisan menyebabkan biaya tambahan? [Tutup]


12

Jadi saya ingin mewarisi dari sealed classdalam CSharp dan terbakar. Tidak ada cara untuk membuka segelnya kecuali Anda memiliki akses ke sumbernya.

Kemudian saya berpikir "mengapa sealedada?". 4 bulan lalu. Saya tidak bisa mengetahuinya, meskipun membaca banyak hal tentang itu, seperti:

Saya sudah mencoba mencerna semua itu sejak itu, tetapi itu terlalu banyak bagi saya. Akhirnya, kemarin saya mencobanya lagi. Saya telah memindai semuanya lagi, ditambah beberapa lainnya:

Akhirnya, setelah banyak merenungkan, saya memutuskan untuk berat mengedit pertanyaan asli berdasarkan judul baru.

Pertanyaan lama itu terlalu luas dan subyektif. Itu pada dasarnya bertanya:

  1. Dalam judul lama: Satu alasan bagus untuk menggunakan disegel
  2. Di dalam tubuh: Bagaimana cara memodifikasi kelas yang disegel dengan benar? Lupakan tentang warisan? Gunakan komposisi?

Tetapi sekarang, dengan memahami (yang saya tidak lakukan kemarin) bahwa semua yang sealeddilakukan adalah mencegah warisan , dan kita dapat dan memang harus menggunakan komposisi daripada warisan , saya menyadari apa yang saya butuhkan adalah contoh - contoh praktis .

Saya kira pertanyaan saya di sini adalah (dan sebenarnya selalu) persis seperti yang disarankan Mr.Mindor dalam obrolan : Bagaimana mendesain pewarisan dapat menyebabkan biaya tambahan?


5
Pertanyaan itu diucapkan dengan cukup agresif dan terdengar seperti kata-kata kasar. Anda harus menulis ulang jika Anda menginginkan jawaban yang relevan dan objektif.
Euforia

11
Lihat Mengapa Banyak Kelas Kerangka Disegel? oleh Eric Lippert. Dia memberikan beberapa alasan bagus untuk menutup kelas.
Robert Harvey

9
Maka Anda tidak membaca artikel itu. Kembali dan baca lagi. Ini bermuara pada ini: Anda tidak dapat memprediksi cara yang tak terhitung banyaknya klien dapat mematahkan kelas Anda dengan memperluasnya. Anda dapat menyalahkan klien Anda untuk itu, tetapi kaulah yang harus mendukung mereka.
Robert Harvey

4
@Cawas Dia bisa, atau Anda bisa membaca artikel yang dia tautkan yang menjelaskannya secara terperinci. Dia hanya meringkas artikel itu dengan komentarnya.
Servy

7
Maaf, tapi saya bukan orang yang mengoceh di sini. Jawaban untuk pertanyaan Anda sangat sederhana: segel kelas ketika Anda tidak ingin mendukung warisan. Itu dia.
Robert Harvey

Jawaban:


27

Ini tidak begitu sulit untuk dipahami. sealeddiciptakan secara khusus untuk Microsoft untuk membuat hidup mereka lebih mudah, menghemat banyak uang dan membantu reputasi mereka. Karena ini adalah fitur bahasa yang semua orang dapat menggunakannya juga tetapi ANDA mungkin tidak akan pernah perlu menggunakan yang disegel.

Kebanyakan orang mengeluh tentang tidak dapat memperpanjang kelas dan jika mereka melakukannya maka mereka berkata baik semua orang tahu itu adalah tanggung jawab pengembang untuk membuatnya bekerja dengan benar. Itu benar, KECUALI orang-orang yang sama tidak memiliki petunjuk tentang sejarah Windows dan salah satu masalah sealedsedang mencoba untuk menyelesaikannya.

Mari kita misalkan pengembang memperluas kelas inti .Net (karena disegel tidak ada) dan membuatnya bekerja dengan sempurna. Yay, untuk pengembang. Pengembang mengirimkan produk ke pelanggan. Aplikasi pengembang berfungsi dengan baik. Pelanggan itu senang. Hidup itu baik.

Sekarang Microsoft merilis sistem operasi baru, yang mencakup memperbaiki bug dalam kelas inti .Net khusus ini. Pelanggan ingin mengikuti perkembangan zaman dan memilih untuk menginstal sistem operasi baru. Tiba-tiba, aplikasi yang disukai pelanggan tidak lagi berfungsi, karena tidak memperhitungkan bug yang diperbaiki di kelas inti .Net.

Siapa yang disalahkan?

Mereka yang akrab dengan sejarah Microsoft tahu bahwa OS baru Microsoft akan disalahkan dan bukan perangkat lunak aplikasi yang menyalahgunakan pustaka windows. Jadi itu menjadi tugas Microsoft untuk memperbaiki masalah, bukan perusahaan aplikasi yang menciptakan masalah. Ini adalah salah satu alasan mengapa kode Windows menjadi kembung. Dari apa yang saya baca, kode sistem operasi Windows dikotori dengan spesifik if-then memeriksa apakah aplikasi dan versi spesifik sedang berjalan dan jika demikian maka lakukan beberapa pemrosesan khusus untuk memungkinkan program berfungsi. Itu banyak uang yang dihabiskan oleh Microsoft untuk memperbaiki ketidakmampuan perusahaan lain.

Menggunakan sealedtidak sepenuhnya menghilangkan skenario di atas, tetapi itu membantu.


4
@ Cawas Cukup sulit untuk menyalahgunakannya. Eric Lippert telah menyatakan pada sejumlah kesempatan dia berharap bahwa kelas, seperti metode, semuanya sealedsecara default, kecuali secara khusus tidak disegel, hanya karena begitu sedikit kelas yang sebenarnya dirancang untuk diwariskan. Ini jauh lebih mungkin bahwa kelas Anda tidak dibangun untuk mendukungnya, dan Anda harus memastikan bahwa Anda telah menghabiskan waktu dev itu jika Anda pergi keluar dari cara Anda untuk menandainya sebagai tidak tertutup.
Servy

1
Saya pikir jika orang menggunakan disegel untuk perangkat lunak pengembangan internal mereka, mereka mungkin menyalahgunakannya atau hanya membuang-buang waktu perusahaan berusaha menjadi terlalu sempurna. Saya katakan mungkin karena selalu ada kasus yang bisa muncul dalam skenario tertentu. Namun, bagi mereka yang mengembangkan perangkat lunak jenis perpustakaan, saya menduga itu sangat berguna untuk alasan yang sama bahwa Microsoft memutuskan ada kebutuhan untuk itu.
Dunk

2
@Cawas The luas mayoritas kelas yang ditulis oleh sebagian besar pengembang tidak akan pernah perlu diwariskan, dan tidak ditulis untuk dukungan warisan. Ini dapat dengan cepat dan efektif disampaikan kepada pembaca / pengguna kode dengan membuat tipe sealed. Jika itu sebenarnya pilihan default maka itu berarti bahwa jika seseorang mewarisi dari suatu tipe maka mereka akan tahu bahwa itu dibangun untuk mendukungnya.
Servy

2
Membuka segel suatu kelas tidak berarti bahwa kelas itu dibangun untuk mendukungnya. Itu hanya berarti bahwa seseorang ingin mewarisi dari kelas dan membuka segelnya. Dalam kasus terbaik, menggunakan disegel hanya akan menyebabkan pengembang menulis ulang fungsionalitas yang ada (setara dengan kelas disegel) tetapi lebih sering daripada tidak, jika kode sumber tersedia, mereka hanya akan membuka segelnya tanpa memperhitungkan konsekuensi apa pun. Setelah disegel secara khusus dan jarang ditetapkan, lebih baik karena pengembang mungkin ingin mencari tahu mengapa kelas ini disegel. Terlalu banyak kelas tertutup dan mereka tidak akan peduli mengapa.
Dunk

1
Juga keamanan adalah alasan untuk menggunakannya! Pertimbangkan aplikasi kotak pasir yang mencoba mengakses file. Kotak pasir mungkin menguji nama file-string, tetapi bagaimana jika seorang penyerang bisa mengirimkan Anda bisa berubah String dan kemudian mereka bermutasi setelah pemeriksaan keamanan tetapi sebelum I / O? Saya percaya bahwa jenis skenario adalah mengapa Java Stringditandai final(mirip dengan sealed) dan saya bertaruh logika yang sama mendukung beberapa keputusan C #.
Darien

23

sealeddigunakan untuk menunjukkan bahwa penulis kelas belum mendesainnya untuk diwarisi. Tidak kurang, tidak lebih.

Mendesain antarmuka dengan benar sudah cukup sulit bagi banyak programmer. Mendesain kelas dengan benar yang berpotensi diwariskan menambah kesulitan dan garis kode. Semakin banyak baris kode yang ditulis berarti semakin banyak kode yang harus dipelihara. Untuk menghindari kesulitan yang meningkat ini, sealeddapat menunjukkan bahwa kelas tidak pernah dimaksudkan untuk diwariskan, dan dalam konteks ini, menyegel kelas adalah solusi yang valid untuk masalah .

Bayangkan kasus dari mana kelas CustomBoeing787tersebut berasal Airliner. Ini CustomBoeing787menimpa beberapa metode yang dilindungi dari Airliner, tetapi tidak semuanya. Jika pengembang memiliki cukup waktu dan tidak sia-sia, ia dapat menguji unit kelas untuk memastikan bahwa semuanya berfungsi seperti yang diharapkan, bahkan dalam konteks ketika metode non-overriden dipanggil (misalnya setter yang dilindungi yang mengubah keadaan objek). Jika pengembang yang sama (1) tidak punya waktu, (2) tidak ingin menghabiskan tambahan ratusan atau ribuan dolar dari bos / pelanggannya, atau (3) tidak ingin menulis kode tambahan dia tidak butuhkan sekarang (YAGNI), maka dia dapat:

  • baik merilis kode di alam liar, mengingat bahwa itu adalah perhatian para programmer yang akan memelihara proyek ini nanti untuk peduli tentang bug potensial,

  • atau tandai kelas sealeduntuk secara eksplisit menunjukkan kepada programmer masa depan bahwa kelas ini tidak dimaksudkan untuk diwariskan, dan bahwa membuka segelnya dan menggunakannya sebagai orangtua harus dilakukan dengan risiko Anda sendiri.

Apakah ide yang bagus untuk menyegel kelas sebanyak mungkin, atau sesedikit mungkin? Dari pengalaman saya, tidak ada jawaban yang pasti. Beberapa pengembang cenderung menggunakan sealedterlalu banyak; yang lain tidak peduli tentang bagaimana kelas akan diwarisi dan masalah yang disebabkannya. Mengingat penggunaan tersebut, masalahnya mirip dengan yang terdiri dalam menentukan apakah programmer harus menggunakan dua atau empat ruang untuk lekukan: tidak ada jawaban yang benar.


Baiklah ... Maaf jika saya terdengar agresif lagi, tapi saya hanya ingin menjadi jelas dan tegas di sini ... Saya hanya bisa mengerti apa yang baru saja Anda tulis dalam salah satu dari dua cara, jika Anda ingin menulis di tl;drsini. Itu bisa berupa "Tidak, tidak ada satu pun alasan bagus" , atau "Saya pikir tidak ada alasan yang bagus, tetapi saya tidak tahu juga." . Bagi saya, "tidak ada jawaban pasti" adalah salah satunya.
cregox

6
sealeddigunakan untuk menunjukkan bahwa penulis kelas belum mendesainnya untuk diwarisi. Itulah satu-satunya alasan bagus Anda.
Robert Harvey

Itu alasan yang bagus untuk memberi Anda sepeda tanpa lampu dan memaksakan, entah bagaimana, Anda tidak bisa menambahkan lampu.
cregox

2
@ Cawas Bagaimana? Dalam konteks bahwa itu tidak penting untuk pembangun sepeda untuk memastikan bahwa sepeda tidak memiliki cahaya, tetapi sering adalah penting bagi pengguna jenis untuk memastikan bahwa pelaksanaan adalah implementasi yang tepat tertentu. Anda menegakkan batasan yang Anda butuhkan. Dalam beberapa kasus orang dapat menambahkan kendala yang sebenarnya tidak diperlukan; Anda telah memberikan contohnya. Hanya karena kendala salah digunakan di satu tempat, tidak berarti Anda tidak boleh membatasi apa pun.
Servy

1
Juga keamanan adalah alasan untuk menggunakannya! Pertimbangkan aplikasi kotak pasir yang mencoba mengakses file. Kotak pasir mungkin menguji nama file-string, tetapi bagaimana jika seorang penyerang bisa mengirimkan Anda bisa berubah String dan kemudian mereka bermutasi setelah pemeriksaan keamanan tetapi sebelum I / O? Saya percaya bahwa jenis skenario adalah mengapa Java Stringditandai final(mirip dengan sealed) dan saya bertaruh logika yang sama mendukung beberapa keputusan C #.
Darien

4

Ketika sebuah kelas disegel, itu memungkinkan kode menggunakan tipe itu untuk tahu persis apa yang mereka hadapi.

Sekarang di C # stringadalah sealed, Anda tidak dapat mewarisi itu, tapi mari kita asumsikan sejenak bahwa itu tidak terjadi. Jika Anda melakukannya, maka seseorang dapat menulis kelas seperti ini:

public class EvilString// : String
{
    public override string ToString()
    {
        throw new Exception("I'm mean");
    }
    public override bool Equals(object obj)
    {
        return false;
    }
    public override int GetHashCode()
    {
        return 0;
    }
}

Ini sekarang akan menjadi kelas string yang melanggar semua jenis properti yang para desainer stringtahu benar. Mereka tahu bahwa Equalsmetodenya akan transitif, ini bukan. Heck, metode yang sama ini bahkan tidak simetris, karena string bisa sama dengan itu tetapi tidak akan sama dengan string itu. Saya yakin ada segala macam programmer yang memiliki kode tertulis dengan asumsi bahwa ToStringmetode stringtidak akan membuang pengecualian untuk nilai-nilai non-nol. Anda sekarang dapat melanggar asumsi itu.

Ada sejumlah kelas lain yang bisa kita gunakan untuk ini, dan segala macam asumsi lain yang bisa kita langgar. Jika Anda menghapus fitur bahasa untuksealedmaka perancang bahasa sekarang harus mulai menghitung hal-hal seperti ini di semua kode perpustakaan mereka. Mereka perlu melakukan segala macam pemeriksaan untuk memastikan bahwa tipe yang diperluas dari tipe yang ingin mereka gunakan akan ditulis "dengan benar", yang bisa menjadi hal yang sangat mahal untuk dilakukan (baik pada waktu dev, maupun pada saat run time). Dengan mampu menyegel kelas, mereka dapat memastikan bahwa ini tidak mungkin, dan bahwa setiap pernyataan yang mereka buat tentang detail implementasi dari tipe mereka sendiri tidak dapat dilanggar, kecuali untuk tipe-tipe yang sengaja dirancang untuk diperluas. Untuk jenis yang dirancang untuk diperpanjang Anda akan menemukan kode bahasa harus jauh lebih defensif tentang bagaimana menangani mereka.


Tetapi Anda dapat melanggar asumsi itu dalam kode Anda . Ini tidak seperti Anda mengambil sumber String dan mengeditnya. Para desainer tidak perlu memperhitungkan ini karena 1 daun, 1 cabang, 1 klien menggunakannya dengan risiko dan kebijaksanaannya sendiri. Itu tidak akan menyebar dari sana, kecuali klien lain lebih suka melakukannya. Dan seterusnya.
cregox

3
@ Cawas Dan jika pengecualian dilemparkan pada waktu yang tidak terduga dan sumber daya bocor sebagai hasilnya, atau kelas dibiarkan dalam keadaan tak tentu dan fungsinya tidak sesuai? Kasus ini agak konyol, tetapi bisa dengan mudah seseorang menulis implementasi yang mereka pikir masuk akal, tetapi kadang-kadang melempar ketika seharusnya tidak, atau tidak bekerja dengan nilai-nilai tertentu. Mereka kemudian akan mengeluh ketika kode bahasa tidak berfungsi. Lebih baik tidak membiarkan orang melakukan hal-hal yang tidak dapat didukung oleh bahasa.
Servy

Bagaimanapun Anda berbicara tentang membangun kompiler. Ada banyak sealedfitur built-in di sana yang tidak terpapar untuk kita gunakan. Itu masih tidak menjelaskan mengapa menggunakannya di luar lingkup yang sempit dan, karena sesempit kode kompiler , bahkan tidak menjelaskan sealedkeberadaan.
cregox

2
@Cawas stringTipe ini bukan kode kompiler. Itu bagian dari kode bahasa. Benar-benar berbeda. Bagaimanapun, saya hanya mengambil satu contoh. Anda bisa mengambil sebagian besar kelas tersegel di seluruh BCL dan menggunakannya sebagai contoh.
Servy

4
@ Cawas: Saya pikir apa yang mungkin Anda lewatkan di sini adalah aspek dukungan pelanggan. Jika Anda membiarkan suatu kelas bisa diwariskan, pelanggan akan mewarisi darinya, dan kemudian mereka akan memanggil Anda ketika kelas itu rusak. Anda dapat memberi tahu mereka sepanjang hari bahwa mereka mewarisi dari kelas itu dengan risiko mereka sendiri, tetapi Anda masih akan menerima telepon itu, karena Anda membiarkan mereka mewarisinya, sehingga mereka menganggap aman untuk melakukannya.
Robert Harvey

3

Apakah ada alasan bagus untuk menggunakan disegel?

Tingkatkan? Tidak sering. Saya hanya akan menggunakan disegel ketika saya memiliki tipe yang tidak dapat diubah (atau batasan lainnya) yang benar- benar harus tetap tidak dapat diubah dan saya tidak dapat mempercayai pewaris untuk memenuhi persyaratan tersebut tanpa memasukkan bug yang halus dan berbahaya ke dalam sistem.

Misalkan ada alasan yang baik untuk menggunakan disegel dan kita harus menggunakannya sebagai standar untuk semuanya, apa yang kita lakukan dengan warisan?

Kami menggunakan warisan untuk hal-hal yang tidak standar. Bahkan jika komposisi lebih disukai daripada warisan (dan memang demikian), itu tidak berarti warisan harus dibuang. Ini berarti bahwa warisan memiliki beberapa masalah intrinsik yang diperkenalkan ke dalam desain dan pemeliharaan kode dan komposisi melakukan banyak hal yang sama dengan (secara umum) lebih sedikit masalah. Dan itu berarti bahwa bahkan jika komposisi disukai bahwa pewarisan itu baik untuk himpunan bagian masalah tertentu.

Saya tidak bermaksud terlalu kejam, tetapi jika Anda baru saja mendengar tentang SOLID dan pengujian unit, mungkin Anda harus keluar dari bawah batu Anda dan benar-benar menulis kode. Hal-hal yang tidak jelas dipotong, dan jarang akan "selalu melakukan X" atau "tidak pernah menggunakan Y" atau "Z adalah yang terbaik" menjadi cara yang benar (seperti tampaknya Anda tertarik berdasarkan pandangan pertanyaan Anda). Saat Anda menulis kode, Anda dapat melihat kasus-kasus di mana sealedbisa menjadi baik dan kasus-kasus di mana hal itu menyebabkan Anda bersedih - seperti pengorbanan lainnya.


Bagi saya, ini dan "untuk menghindari keharusan mendukung warisan kepada klien" yang tidak ingin dijelaskan oleh Robert adalah jawaban yang paling menjanjikan ... Mungkin Anda bisa menguraikan lebih lanjut tentang kasus-kasus di mana Anda menggunakannya sealed, tolong?
cregox

@ Cawas - Saya tidak yakin saya bisa. Saya sangat jarang melakukannya, dan sering kali merupakan tradeoff di mana jaminan bahwa sesuatu tetap abadi (untuk membuat optimasi kinerja, penyederhanaan desain) bernilai ketidakmampuan untuk mewarisi dari objek.
Telastyn

Itu keren. Dunk sudah menenggelamkannya! : P Terima kasih banyak atas jawabannya. Dan Anda adalah satu-satunya yang mengambil "petunjuk halus" saya tentang keahlian saya. Sepertinya orang menganggap saya tahu lebih banyak, saya tidak tahu ... Tapi saya berharap "hanya coding" akan membawa saya keluar dari batu ini. Mungkin saya memang menerapkan konsep-konsep itu dengan cara tertentu, hanya saja tidak secara prosedural seperti yang seharusnya.
cregox

3

Pertama-tama, Anda harus membaca posting Eric Lippert tentang mengapa Microsoft menyegel kelas mereka.

http://blogs.msdn.com/b/ericlippert/archive/2004/01/22/61803.aspx

Kedua, kata kunci yang disegel ada untuk melakukan apa yang dilakukannya - mencegah pewarisan. Ada banyak situasi di mana Anda ingin mencegah warisan. Pertimbangkan kelas yang Anda punya koleksi. Jika kode Anda bergantung pada kelas yang bekerja dengan cara tertentu, Anda tidak ingin seseorang menimpa salah satu metode atau properti di kelas itu dan menyebabkan aplikasi Anda gagal.

Ketiga, menggunakan disegel mendorong komposisi atas warisan, yang merupakan kebiasaan yang baik untuk dimasuki. Menggunakan komposisi lebih dari warisan berarti Anda tidak dapat melanggar prinsip substitusi Liskov dan Anda mengikuti prinsip Terbuka / Tertutup. sealedOleh karena itu kata kunci yang membantu Anda dalam mengikuti dua dari lima prinsip terpenting pemrograman oo. Saya akan mengatakan itu menjadikannya fitur yang sangat berharga.


Bagian pertama sudah ditunjukkan dalam komentar pertanyaan. Bagian kedua adalah lebih banyak alasan tanpa sebab nyata. Bagian ketiga, meskipun sudah mendekati tempat lain, mungkin memiliki sesuatu untuk itu. Saya akan fokus pada yang itu.
cregox

poin ketiga tidak mendorong komposisi lebih dari warisan, itu sepenuhnya menghilangkan warisan sebagai opsi, bahkan jika itu adalah pilihan keseluruhan terbaik.
Michael Shaw

Itu tergantung apakah Anda mengontrol basis kode atau tidak. Jika Anda menyegel kelas, Anda selalu dapat membuka segelnya nanti jika perlu.
Stephen

2

Saya pikir pertanyaan ini tidak memiliki jawaban yang objektif dan semuanya tergantung pada perspektif Anda.

Di satu sisi, beberapa orang menginginkan segalanya "terbuka" dan beban untuk memastikan semuanya bekerja dengan benar adalah pada orang yang memperluas kelas. Inilah sebabnya mengapa kelas terbuka untuk warisan secara default. Dan mengapa metode Java semuanya virtual secara default.

Di sisi lain, beberapa ingin semuanya ditutup secara default dan memberikan opsi untuk membukanya. Dalam hal ini, pengarang kelas dasar yang perlu memastikan semua yang ia buat "terbuka" aman untuk digunakan dengan cara apa pun yang bisa dibayangkan. Inilah sebabnya mengapa dalam C # semua metode adalah non-virtual secara default dan perlu dinyatakan virtual untuk diganti. Ini juga untuk orang-orang itu, yang perlu menjadi cara untuk menghindari default "terbuka". Seperti membuat kelas tersegel / final, karena mereka melihat seseorang berasal dari kelas masalah besar untuk desain kelas mereka sendiri.


Ini lebih seperti itu! Ini mungkin alasan yang bagus ... "Karena orang ingin menutupnya". Dan itu juga yang ingin saya katakan dalam pertanyaan: sepertinya kelas non-virtual di C ++ dapat diganti. sealedtidak bisa. Bagaimana kita bisa mewarisi dari mereka? Yang saya baca adalah kita tidak bisa. Pernah. Saya tidak tahu Saya sudah bolak-balik tentang hal ini selama 4 bulan sekarang, sejak saya pertama kali mendengar tentang disegel. Dan saya masih tidak tahu bagaimana melakukannya dengan benar ketika saya perlu memodifikasi apa pun pada kelas yang disegel. Jadi, saya tidak melihat "opsi untuk membukanya"!
cregox

4
Ini bukan mengapa metode kelas C ++ tidak virtual secara default. Membuat metode virtual berarti harus ada overhead tambahan pada tabel metode pencarian, dan C ++ memiliki filosofi bahwa Anda hanya membayar biaya overhead ketika Anda menginginkan fitur tersebut.
Michael Shaw

@ Polemy Ok, saya menghapusnya. Seharusnya saya tidak pernah menulisnya, karena saya tahu orang-orang mulai mengeluh tentang hal itu.
Euforia

hei, saya benar-benar menghargai bahwa jika Anda ingin mengklaim bahwa orang ingin menulis kelas tertutup secara default, dan harus secara aktif memilih untuk membukanya, maka Anda harus berusaha keras
Michael Shaw

IMO sangat mirip dengan debat pribadi / terlindungi / publik ketika menyangkut API: Sangat bergantung pada siapa yang mengontrol kelas, siapa yang ingin mewarisi kelas, komunikasi antara keduanya, dan seberapa sering versi baru keluar.
Darien

-2

masalah dengan disegel dalam C # adalah bahwa itu agak final. Dalam 7 tahun pengembangan komersial C #, satu-satunya tempat saya telah melihat itu digunakan pada Microsoft .NET kelas di mana saya merasa saya punya alasan yang sah untuk memperluas kelas kerangka kerja untuk menerapkan perilaku yang disesuaikan, dan karena kelas disegel, saya tidak bisa .

Tidak mungkin untuk menulis kelas berpikir tentang setiap cara yang mungkin dapat digunakan, dan memutuskan bahwa tidak satu pun dari mereka yang sah. Demikian juga jika kerangka kerja keamanan tergantung pada kelas yang tidak diwariskan, maka Anda memiliki cacat desain keamanan.

Jadi, sebagai kesimpulan, saya dengan tegas berpendapat bahwa disegel tidak memiliki tujuan yang bermanfaat, dan tidak ada yang saya baca di sini sejauh ini telah mengubah pandangan itu.

Saya bisa melihat sejauh ini ada tiga argumen yang membenarkan disegel ditempatkan sejauh ini.

  1. Argumen 1 adalah bahwa ia menghilangkan sumber bug ketika orang mewarisi dari kelas dan kemudian meningkatkan akses ke internal kelas itu tanpa benar-benar memahami internal dengan benar.

  2. Argumen 2 adalah bahwa jika Anda memperpanjang kelas microsoft dan kemudian microsoft menerapkan perbaikan bug di kelas itu tetapi ekstensi Anda mengandalkan bug itu maka kode Anda sekarang rusak, microsoft disalahkan, dan disegel mencegah bahwa

  3. Argumen 3 adalah bahwa sebagai pengembang kelas, pilihan saya adalah apakah Anda akan memperpanjangnya, sebagai bagian dari desain kelas saya.

Argumen 1 tampaknya merupakan argumen bahwa Anda para programmer akhir tidak tahu bagaimana menggunakan kode saya. Itu mungkin terjadi, tetapi jika Anda masih mengizinkan saya untuk mengakses objek antarmuka itu masih berlaku bahwa saya menggunakan objek Anda, dan membuat panggilan ke sana tanpa memahami cara menggunakannya, dan dengan demikian dapat membuat kerusakan sebanyak itu . Ini adalah justifikasi yang lemah akan perlunya disegel.

Saya mengerti dari mana basis faktual untuk arg 2 berasal. Khususnya ketika microsoft melakukan pemeriksaan tambahan OS pada win32 api call untuk mengidentifikasi panggilan yang salah, yang telah meningkatkan stabilitas umum Windows XP dibandingkan dengan Windows NT, tetapi dengan biaya jangka pendek banyak aplikasi yang rusak ketika Windows XP dirilis. Microsoft menyelesaikan ini dengan memasukkan 'aturan' agar cek ini dapat dikatakan, abaikan ketika aplikasi X melanggar aturan ini, ini merupakan bug yang dikenal

Argumen 2 adalah argumen yang buruk karena disegel paling tidak membuat perbedaan dengan ini karena jika ada bug di perpustakaan .NET Anda tidak punya pilihan selain mencari pekerjaan, dan ketika perbaikan microsoft keluar, kemungkinan besar berarti pekerjaan Anda di sekitar yang tergantung pada perilaku yang rusak sekarang rusak. Apakah Anda menyiasatinya dengan menggunakan warisan atau kode pembungkus tambahan lainnya, saat kode itu diperbaiki, pekerjaan Anda di sekitar akan rusak.

Argumen 3 adalah satu-satunya argumen yang memiliki substansi apa pun untuk membenarkan dirinya sendiri. Namun masih lemah. Itu hanya bertentangan dengan butir penggunaan kembali kode.


2
/ saya mengirim email ke microsoft, tolong buka segel kelas X untuk saya dan kirimkan rilis baru .NET. salam, .... Seperti yang saya katakan, satu-satunya waktu dalam pengembangan komersial saya telah melihat kelas yang disegel, tidak mungkin untuk membuka segelnya.
Michael Shaw

6
It is impossible to write a class thinking about every possible way it could be used- Itulah alasan mengapa banyak kelas Framework disegel ... Ini menghilangkan kebutuhan untuk memikirkan setiap cara yang mungkin dilakukan seseorang untuk memperluas kelas.
Robert Harvey

5
Jika Anda bisa membuka segelnya, tidak ada gunanya menyegelnya, bukan?
Robert Harvey

2
@Ptolemy Memungkinkan orang untuk memperluas kelas Anda adalah fitur . Salah satu yang mengkonsumsi sejumlah besar upaya pengembangan. Ini adalah fitur yang hanya layak untuk dibenarkan jika penulis kelas dapat melihat manfaat yang cukup dalam ekstensi potensial untuk membenarkan upaya tersebut. Jika mereka tidak dapat membenarkan upaya tersebut, dan oleh karena itu jenis dan penggunanya tidak dibangun untuk mendukung ekstensi, maka penting untuk mencegahnya, jika tidak Anda akan secara teknis dapat memperluas jenisnya, tetapi itu tidak akan berfungsi dengan baik ketika kamu melakukannya.
Servy

2
@ Cawas: Kamu hanya sulit.
Robert Harvey


-8

Seperti yang dibuktikan oleh pertanyaan saya, saya bukan ahli di sini. Tetapi saya tidak melihat alasan untuk sealedbahkan ada.

Tampaknya dibuat untuk membantu arsitek kode untuk mendesain antarmuka. Jika Anda ingin menulis kelas yang akan keluar di alam liar dan banyak orang akan mewarisi darinya, memodifikasi apa pun di kelas itu dapat merusaknya karena terlalu banyak orang. Jadi kita bisa menyegelnya dan tidak ada yang bisa mewarisinya. "Masalah terpecahkan".

Yah, sepertinya "menutupi tempat dan mengungkap yang lain". Dan itu bahkan tidak menyelesaikan masalah - itu hanya menghilangkan alat : warisan. Sebagai alat apa pun, ia memiliki banyak penggunaan dan mewarisi dari kelas yang tidak stabil adalah risiko yang Anda ambil. Siapa pun yang mengambil risiko itu harus tahu lebih baik.

Mungkin ada kata kunci stable, jadi orang akan tahu lebih aman untuk mewarisi kata kunci tersebut.


2
"Masalah terpecahkan" - Tepat.
Robert Harvey

@RobertHarvey Tidak terpecahkan, seperti yang dijelaskan di paragraf berikutnya.
cregox

8
Anda hanya marah karena Anda tidak dapat memperpanjang kelas. Itu tidak berarti bahwa sealeditu bukan alat yang berguna bagi perancang kerangka kerja. Kelas dalam suatu kerangka kerja harus kotak hitam; Anda tidak perlu tahu tentang internal kelas untuk dapat menggunakannya dengan benar. Namun itulah yang dituntut oleh warisan.
Robert Harvey

Saya tidak pernah mengatakan itu tidak berguna. Saya katakan saya tidak melihat penggunaannya, dan menunjukkan mengapa. Tolong, saya mohon, beri saya alasan yang bagus untuk menggunakannya! Bahkan jika itu hanya "karena saya ingin mengikuti pola desain tertutup", itu tidak masalah. Saya tidak melihat ada yang memberikan alasan itu, secara eksplisit.
cregox

7
Alasan baiknya adalah Anda tidak harus mendukung warisan pada kelas yang disegel.
Robert Harvey
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.