Saya memiliki beberapa kelas yang tidak benar-benar membutuhkan keadaan apa pun. Dari sudut pandang organisasi, saya ingin menempatkan mereka dalam hierarki.
Tapi sepertinya saya tidak bisa mendeklarasikan pewarisan untuk kelas statis.
Sesuatu seperti itu:
public static class Base
{
}
public static class Inherited : Base
{
}
tidak akan berfungsi.
Mengapa para perancang bahasa menutup kemungkinan itu?
c#
inheritance
static
Pengguna
sumber
sumber
Jawaban:
Kutipan dari sini :
Pendapat lain dari channel9
Dan sebagai ide yang berharga, littleguru memiliki "solusi" parsial untuk masalah ini: pola Singleton .
sumber
object
, dan semua orang diharapkan mengetahuinya. Jadi kelas statis selalu diwarisi dariobject
, apakah Anda menentukannya secara eksplisit atau tidak.Alasan utama bahwa Anda tidak dapat mewarisi kelas statis adalah karena mereka abstrak dan disegel (ini juga mencegah setiap instance dari mereka dibuat).
Jadi ini:
kompilasi untuk IL ini:
sumber
Pikirkan seperti ini: Anda mengakses anggota statis melalui nama tipe, seperti ini:
Jika Anda mewarisi dari kelas itu, Anda harus mengaksesnya melalui nama tipe baru:
Dengan demikian, item baru tidak memiliki hubungan dengan aslinya ketika digunakan dalam kode. Tidak akan ada cara untuk mengambil keuntungan dari hubungan pewarisan untuk hal-hal seperti polimorfisme.
Mungkin Anda berpikir Anda hanya ingin memperpanjang beberapa item di kelas asli. Dalam hal itu, tidak ada yang mencegah Anda dari hanya menggunakan anggota asli dalam tipe yang sama sekali baru.
Mungkin Anda ingin menambahkan metode ke tipe statis yang ada. Anda dapat melakukannya melalui metode ekstensi.
Mungkin Anda ingin dapat memberikan statis
Type
ke fungsi saat runtime dan memanggil metode pada tipe itu, tanpa tahu persis apa yang dilakukan metode tersebut. Dalam hal ini, Anda dapat menggunakan Antarmuka.Jadi, pada akhirnya Anda tidak benar-benar mendapatkan apa pun dari mewarisi kelas statis.
sumber
SomeClass<T> where T:Foo
dapat mengakses anggotaFoo
, dan jikaT
kelas yang mengalahkan beberapa anggota statis virtualFoo
, kelas generik akan menggunakan penggantian tersebut. Bahkan mungkin untuk mendefinisikan konvensi melalui mana bahasa dapat melakukannya dengan cara yang kompatibel dengan CLR saat ini (misalnya kelas dengan anggota tersebut harus mendefinisikan kelas non-statis yang dilindungi yang berisi anggota instance seperti itu, bersama dengan bidang statis memegang instance dari tipe itu).Apa yang ingin Anda capai dengan menggunakan hierarki kelas dapat dicapai hanya melalui namespacing. Jadi bahasa yang mendukung namespapces (seperti C #) tidak akan menggunakan implementasi hirarki kelas dari kelas statis. Karena Anda tidak dapat membuat instance dari salah satu kelas, yang Anda butuhkan adalah organisasi hirarki definisi kelas yang dapat Anda peroleh melalui penggunaan ruang nama
sumber
Anda dapat menggunakan komposisi sebagai gantinya ... ini akan memungkinkan Anda untuk mengakses objek kelas dari tipe statis. Tetapi masih tidak bisa mengimplementasikan antarmuka atau kelas abstrak
sumber
Meskipun Anda dapat mengakses anggota statis "bawaan" melalui nama kelas bawaan, anggota statis tidak benar-benar diwariskan. Ini sebagian mengapa mereka tidak bisa virtual atau abstrak dan tidak bisa diganti. Dalam contoh Anda, jika Anda mendeklarasikan Base.Method (), kompiler akan memetakan panggilan ke Inherited.Method () kembali ke Base.Method (). Anda mungkin juga memanggil Base.Method () secara eksplisit. Anda dapat menulis tes kecil dan lihat hasilnya dengan Reflector.
Jadi ... jika Anda tidak dapat mewarisi anggota statis, dan jika kelas statis hanya dapat berisi anggota statis, apa gunanya mewarisi kelas statis?
sumber
Hmmm ... apakah akan jauh berbeda jika Anda hanya memiliki kelas non-statis yang diisi dengan metode statis ..?
sumber
Solusi yang dapat Anda lakukan adalah tidak menggunakan kelas statis tetapi sembunyikan konstruktor sehingga anggota kelas statis adalah satu-satunya hal yang dapat diakses di luar kelas. Hasilnya adalah kelas "statis" bawaan pada dasarnya:
Sayangnya karena keterbatasan bahasa "by-design" yang tidak dapat kami lakukan:
sumber
Anda dapat melakukan sesuatu yang akan tampak seperti warisan statis.
Ini triknya:
Maka Anda dapat melakukan ini:
The
Inherited
kelas tidak statis itu sendiri, tapi kami tidak memungkinkan untuk menciptakannya. Ini sebenarnya telah mewarisi konstruktor statis yang dibangunBase
, dan semua properti dan metodeBase
tersedia sebagai statis. Sekarang satu-satunya hal yang harus dilakukan adalah membuat pembungkus statis untuk setiap metode dan properti yang perlu Anda paparkan ke konteks statis Anda.Ada kelemahan seperti kebutuhan untuk pembuatan manual metode pembungkus statis dan
new
kata kunci. Tetapi pendekatan ini membantu mendukung sesuatu yang benar-benar mirip dengan pewarisan statis.PS Kami menggunakan ini untuk membuat kueri yang dikompilasi, dan ini sebenarnya dapat diganti dengan ConcurrentDictionary, tetapi bidang read-only statis dengan keamanan utasnya cukup baik.
sumber
Jawaban saya: pilihan desain yang buruk. ;-)
Ini adalah debat menarik yang berfokus pada dampak sintaksis. Inti dari argumen, dalam pandangan saya, adalah bahwa keputusan desain mengarah ke kelas statis tersegel. Fokus pada transparansi nama-nama kelas statis yang muncul di tingkat atas alih-alih bersembunyi ('membingungkan') di balik nama anak? Orang dapat membayangkan implementasi bahasa yang dapat mengakses pangkalan atau anak secara langsung, membingungkan.
Contoh pseudo, dengan asumsi pewarisan statis didefinisikan dalam beberapa cara.
akan mengarah ke:
yang dapat (akan?) memengaruhi penyimpanan yang sama dengan
Sangat membingungkan!
Tapi tunggu! Bagaimana kompiler menangani MyStaticBase dan MyStaticChild memiliki tanda tangan yang sama di keduanya? Jika anak menimpa daripada contoh saya di atas TIDAK akan mengubah penyimpanan yang sama, mungkin? Hal ini menyebabkan lebih banyak kebingungan.
Saya percaya ada pembenaran ruang informasi yang kuat untuk pewarisan statis terbatas. Lebih lanjut tentang batas tak lama. Kodesemu ini menunjukkan nilainya:
Maka Anda mendapatkan:
Penggunaannya terlihat seperti:
Orang yang menciptakan anak statis tidak perlu memikirkan proses serialisasi selama mereka memahami batasan apa pun yang mungkin ditempatkan pada mesin serialisasi platform atau lingkungan.
Statika (lajang dan bentuk 'global' lainnya) sering muncul di sekitar penyimpanan konfigurasi. Warisan statis akan memungkinkan alokasi tanggung jawab semacam ini diwakili dengan rapi dalam sintaksis agar sesuai dengan hierarki konfigurasi. Meskipun, seperti yang saya tunjukkan, ada banyak potensi ambiguitas masif jika konsep pewarisan statis dasar diterapkan.
Saya percaya pilihan desain yang tepat adalah untuk memungkinkan warisan statis dengan batasan spesifik:
Anda masih dapat mengubah toko yang sama melalui referensi umum
MyStaticBase<ChildPayload>.SomeBaseField
. Tetapi Anda akan berkecil hati karena jenis generik harus ditentukan. Sedangkan referensi anak akan menjadi lebih bersih:MyStaticChild.SomeBaseField
.Saya bukan penulis kompiler jadi saya tidak yakin apakah saya kehilangan sesuatu tentang kesulitan menerapkan batasan ini dalam kompiler. Yang mengatakan, saya sangat percaya bahwa ada kebutuhan ruang informasi untuk pewarisan statis terbatas dan jawaban dasarnya adalah Anda tidak bisa karena pilihan desain yang buruk (atau terlalu sederhana).
sumber
Kelas statis dan anggota kelas digunakan untuk membuat data dan fungsi yang dapat diakses tanpa membuat turunan kelas. Anggota kelas statis dapat digunakan untuk memisahkan data dan perilaku yang independen dari identitas objek apa pun: data dan fungsi tidak berubah terlepas dari apa yang terjadi pada objek. Kelas statis dapat digunakan ketika tidak ada data atau perilaku di kelas yang tergantung pada identitas objek.
Kelas dapat dideklarasikan statis, yang menunjukkan bahwa itu hanya berisi anggota statis. Tidak mungkin menggunakan kata kunci baru untuk membuat instance kelas statis. Kelas statis dimuat secara otomatis oleh .NET Framework common language runtime (CLR) ketika program atau namespace yang berisi kelas dimuat.
Gunakan kelas statis untuk memuat metode yang tidak terkait dengan objek tertentu. Misalnya, itu adalah persyaratan umum untuk membuat seperangkat metode yang tidak bertindak atas data contoh dan tidak terkait dengan objek tertentu dalam kode Anda. Anda bisa menggunakan kelas statis untuk menampung metode-metode itu.
Berikut ini adalah fitur utama dari kelas statis:
Mereka hanya berisi anggota statis.
Mereka tidak bisa dipakai.
Mereka dimeteraikan.
Mereka tidak dapat mengandung Instance Constructors (Panduan Pemrograman C #).
Karena itu, membuat kelas statis pada dasarnya sama dengan membuat kelas yang hanya berisi anggota statis dan konstruktor pribadi. Konstruktor pribadi mencegah kelas agar tidak dipakai.
Keuntungan menggunakan kelas statis adalah bahwa kompiler dapat memeriksa untuk memastikan bahwa tidak ada anggota instance ditambahkan secara tidak sengaja. Kompiler akan menjamin bahwa instance dari kelas ini tidak dapat dibuat.
Kelas statis disegel dan karenanya tidak dapat diwarisi. Mereka tidak dapat mewarisi dari kelas apa pun kecuali Object. Kelas statis tidak dapat mengandung konstruktor instance; Namun, mereka dapat memiliki konstruktor statis. Untuk informasi lebih lanjut, lihat Konstruktor Statis (Panduan Pemrograman C #).
sumber
Ketika kita membuat kelas statis yang hanya berisi anggota statis dan konstruktor pribadi. Satu-satunya alasan adalah bahwa konstruktor statis mencegah kelas dari yang dipakai untuk itu kita tidak bisa mewarisi kelas statis. Satu-satunya cara untuk mengakses anggota kelas statis dengan menggunakan nama kelas itu sendiri. Mencoba mewarisi kelas statis bukanlah ide yang baik.
sumber