Pertanyaan Memberi anggota statis


Saya memiliki kelas dasar yang memiliki anggota statis pribadi:

class Base
{
    private static Base m_instance = new Base();
    public static Base Instance
    {
        get { return m_instance; }
    }
}

Dan saya ingin memperoleh beberapa kelas dari ini:

class DerivedA : Base {}
class DerivedB : Base {}
class DerivedC : Base {}

Namun, pada titik ini memanggil DerivedA :: Instance akan mengembalikan objek persis sama seperti DerivedB :: Instance dan DerivedC :: Instance. Saya bisa menyelesaikan ini dengan mendeklarasikan instance di kelas turunan, tetapi kemudian setiap kelas turunan tunggal harus melakukan itu dan sepertinya itu tidak perlu. Jadi adakah cara untuk meletakkan semua ini di kelas dasar? Mungkinkah pola desain diterapkan?


3
2017-12-05 16:18


asal


Jawaban:


Ada satu cara yang benar-benar menjijikkan untuk melakukan ini:

class Base
{
     // Put common stuff in here...
}

class Base<T> : Base where T : Base<T>, new()
{
    private static T m_instance = new T();

    public static T Instance { get { return m_instance; } }
}

class DerivedA : Base<DerivedA> {}
class DerivedB : Base<DerivedB> {}
class DerivedC : Base<DerivedC> {}

Ini berfungsi karena ada satu variabel statis per jenis yang dikonstruksi - mis. List<string> adalah tipe yang berbeda List<int> dan akan memiliki variabel statis terpisah.

Saya telah mengambil kesempatan menjadikannya sebagai turunan kelas turunan juga - saya tidak tahu apakah itu yang Anda inginkan atau tidak, tetapi saya pikir setidaknya saya akan menyediakannya untuk Anda :)

Secara umum, ini adalah hal yang buruk untuk dilakukan. Variabel statis tidak benar-benar dirancang untuk penggunaan semacam ini - saya baru saja menyalahgunakan fitur generik untuk mendapatkan "semacam" perilaku yang Anda minta.

Juga perhatikan itu Base<DerivedA>.Instance akan mengembalikan hasil yang sama dengan DerivedA.Instance - properti / variabel tidak "tahu" yang Anda gunakan DerivedA.Instance. Saya tidak tahu apakah itu penting bagi Anda atau tidak.

Dengan kelas non-generik tambahan, Anda dapat menulis:

Base t = DerivedA.Instance;
t = DerivedB.Instance;

Jika Anda tidak membutuhkannya, keluarkan itu :)


11
2017-12-05 16:21



Metode statis tidak mendukung polimorfisme, oleh karena itu, hal semacam itu tidak mungkin.

Pada dasarnya, properti Instance tidak tahu bagaimana Anda menggunakannya. Dan implementasi tunggal akan ada, karena statis. Jika Anda benar-benar ingin melakukan ini, solusi "tidak direkomendasikan" ini tersedia (saya mendapatkan ide dari solusi Jon):

private static Dictionary<Type, Base> instances = new Dictionary<Type, Base>();
public static T GetInstance<T>() where T : Base, new() {
  Type ty = typeof(T);
  T x;
  if (instances.TryGetValue(ty, out x)) return x;
  x = new T();
  instances[ty] = x;
  return x;
}

6
2017-12-05 16:21



Jawaban singkat: bukan yang saya sadari. Anggota statis selalu nonvirtual dan tidak siap mendukung polimorfisme.

Namun, Anda juga harus bertanya pada diri sendiri Mengapa kamu melakukan ini. Biasanya, anggota statis adalah sumber daya bersama bahwa setiap instance dari kelas itu (termasuk kelas turunan) akan berguna. Namun, ketika Anda membuat contoh statis, Anda biasanya membangun pola tunggal. Dalam hal ini, Anda biasanya ingin menyegel kelas sehingga Anda tidak dapat memiliki kelas turunan, sehingga render seluruh titik diperdebatkan. Jadi, Anda harus benar-benar menganalisis mengapa Anda ingin melakukan ini dan menyelesaikan masalah itu.


3
2017-12-05 16:29