Haruskah kelas tahu tentang subkelasnya? Haruskah suatu kelas melakukan sesuatu yang spesifik untuk subkelas tertentu misalnya?
Naluriku mengatakan bahwa itu adalah desain yang buruk, sepertinya semacam anti-pola.
Haruskah kelas tahu tentang subkelasnya? Haruskah suatu kelas melakukan sesuatu yang spesifik untuk subkelas tertentu misalnya?
Naluriku mengatakan bahwa itu adalah desain yang buruk, sepertinya semacam anti-pola.
Jawaban:
Jawaban yang tersirat oleh konsep kelas adalah "tidak".
Entah tindakan, data, atau relasi apa pun yang Anda tangani adalah bagian dari semua subclass - maka itu harus ditangani dalam superclass tanpa memeriksa tipe yang sebenarnya. Atau itu hanya berlaku untuk beberapa subclass - maka Anda harus melakukan pemeriksaan tipe run-time untuk melakukan hal yang benar, superclass harus diubah setiap kali orang lain mewarisi darinya (atau mungkin diam-diam melakukan hal yang salah), perubahan pada kelas turunan dapat merusak superclass yang tidak berubah, dll
Singkatnya, Anda mendapatkan sejumlah konsekuensi buruk yang biasanya cukup buruk untuk menolak solusi semacam itu. Jika beberapa subclass Anda melakukan hal yang sama dan Anda ingin menghindari duplikasi kode (praktis selalu merupakan hal yang baik), solusi yang lebih baik adalah dengan memperkenalkan kelas tingkat menengah dari mana semua subclass tersebut dapat mewarisi kode.
Tidak hanya seandainya tidak tahu, ia juga tidak bisa ! Biasanya, kelas dapat diperpanjang kapan saja, di mana saja. Itu dapat diperpanjang oleh kelas yang bahkan tidak ada ketika ditulis.
Beberapa bahasa memungkinkan kelas yang diperluas dikendalikan oleh superclass. Dalam Scala, sebuah kelas dapat ditandai sebagai sealed
, yang berarti bahwa ia hanya dapat diperluas oleh kelas-kelas lain dalam unit kompilasi yang sama (file sumber). Namun, kecuali jika subclass tersebut juga sealed
atau final
, subclass kemudian dapat diperpanjang oleh kelas lain.
Dalam Scala, ini digunakan untuk memodelkan tipe data aljabar tertutup, sehingga List
tipe Haskell kanonik :
data List a = Nil | Cons a (List a)
dapat dimodelkan dalam Scala seperti ini:
sealed trait List[+A]
case object Nil extends List[Nothing]
final case class Cons[+A] extends List[A]
Dan Anda dapat menjamin bahwa hanya dua sub "kelas" yang ada karena List
ini sealed
dan dengan demikian tidak dapat diperpanjang di luar file, Cons
adalah final
dan dengan demikian tidak dapat diperpanjang sekali dan Nil
merupakan object
yang tidak dapat diperpanjang pula.
Tapi ini adalah kasus penggunaan khusus (pemodelan tipe data aljabar melalui pewarisan) dan bahkan dalam kasus ini, superclass tidak benar-benar tahu tentang subkelasnya. Ini lebih jaminan kepada pengguna dari List
jenis bahwa jika ia melakukan diskriminasi kasus Nil
dan Cons
, ada tidak akan ada lain alternatif bermunculan di belakang punggungnya.
abstract internal
anggota.
Jawaban sederhananya adalah TIDAK.
Itu membuat kode rapuh dan merusak dua prinsip dasar pemrograman berorientasi objek.
Ya kadang kadang. Misalnya, ketika ada jumlah subclass yang terbatas. Sebuah pola pengunjung adalah sebuah ilustrasi dari kegunaan pendekatan ini.
Contoh: node sintaksis abstrak (AST) dari beberapa tata bahasa yang terdefinisi dengan baik dapat diwarisi dari Node
kelas tunggal yang menerapkan pola pengunjung untuk menangani semua tipe simpul.
Node
, tentu saja, tidak mengandung referensi langsung ke subkelasnya. Tetapi itu berisi accept
metode dengan Visitor
parameter. Dan Visitor
berisi visit
metode per setiap subclass. Jadi, meskipun Node
tidak memiliki referensi langsung ke subkelasnya, ia "tahu" tentang mereka secara tidak langsung, melalui Visitor
antarmuka. Mereka semua digabungkan bersama-sama melaluinya.
Jika saya menulis komponen untuk sebuah perusahaan dan kemudian, setelah saya pergi, seseorang memperluasnya untuk keperluan mereka sendiri, haruskah saya diberitahu tentang itu?
Tidak!
Sama dengan kelas. Percaya dengan nalurimu.