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.
public static class MyStaticBase
{
SomeType AttributeBase;
}
public static class MyStaticChild : MyStaticBase
{
SomeType AttributeChild;
}
akan mengarah ke:
// ...
DoSomethingTo(MyStaticBase.AttributeBase);
// ...
yang dapat (akan?) memengaruhi penyimpanan yang sama dengan
// ...
DoSomethingTo(MyStaticChild.AttributeBase);
// ...
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:
public static class MyStaticBase<T>
{
public static T Payload;
public static void Load(StorageSpecs);
public static void Save(StorageSpecs);
public static SomeType AttributeBase
public static SomeType MethodBase(){/*...*/};
}
Maka Anda mendapatkan:
public static class MyStaticChild : MyStaticBase<MyChildPlayloadType>
{
public static SomeType AttributeChild;
public static SomeType SomeChildMethod(){/*...*/};
// No need to create the PlayLoad, Load(), and Save().
// You, 'should' be prevented from creating them, more on this in a sec...
}
Penggunaannya terlihat seperti:
// ...
MyStaticChild.Load(FileNamePath);
MyStaticChild.Save(FileNamePath);
doSomeThing(MyStaticChild.Payload.Attribute);
doSomething(MyStaticChild.AttributeBase);
doSomeThing(MyStaticChild.AttributeChild);
// ...
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:
- Tidak ada yang menimpa apa pun. Anak tidak dapat mengganti atribut dasar, bidang, atau metode, ... Kelebihan beban harus ok, asalkan ada perbedaan dalam tanda tangan yang memungkinkan kompiler untuk memilah-milah basis anak.
- Hanya izinkan basis statis generik, Anda tidak dapat mewarisi dari basis statis non-generik.
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).