2013-10-08 22 views
16

İlk olarak bir meslektaşımın nesne havuzlarını uygularken bunu yaptığını gördüm. Genel bir temel sınıfa parametre olarak bir araya getirilecek olan sınıfı geçti. Bu temel sınıf, havuz kodunu belirledi.Bir sınıfın kendisini genel bir temel sınıf kötülüğüne bir parametre olarak iletmesine izin mi veriyor?

Tuhaf olan şey, temel sınıfın çocuklarını bilmesidir. Bu her normal durumda kötü uygulama olarak kabul edilir. Ancak bu durumda ebeveyn, tekrarlayan kod yazmamak için sadece teknik bir çözümdür. Temel sınıf asla başka bir kod tarafından başvurulmamaktadır.

Bu konstrüksiyonun bir dezavantajı "temel sınıfı yakar" olmasıdır. Genel taban sınıfını bir hiyerarşinin ortasında tanıtamazsınız. Bu sorun konu dışında olabilir.

public abstract class Singleton<T> where T : class 
{ 
    public static T Instance { get; private set; } 

    public Singleton() 
    { 
     if (Instance != null) 
      throw new Exception("Singleton instance already created."); 
     Instance = (T) (object) this; 
    } 
} 

public class MyClass : Singleton<MyClass> 
{ 
} 

Geliştirilmiş kod: Aşağıda

bir düşünülemez örnektir

public abstract class Singleton<T> where T : Singleton<T> 
{ 
    public static T Instance { get; private set; } 

    public Singleton() 
    { 
     if (Instance != null) 
      throw new Exception("Singleton instance already created."); 
     Instance = (T) this; 
    } 
} 

public class MyClass : Singleton<MyClass> 
{ 
} 

cevap

14

Hayır; Bu, CRTP adı verilen iyi bilinen bir modeldir.
Sanal yöntemlere alternatif olarak C++ 'da özellikle kullanışlıdır.

.Net çerçevesinin içinde IComparable<T> ve IEquatable<T>'da görebilirsiniz.

eklendi dayanıklı olması için, sen where T : Singleton<T>

+0

Aklım bu son cümleyle patlıyor. sınıf TekTon Burada T: Singleton ? Sonsuza dek yinelemeli gitmenizi gerektirmez (her T'nin bir Tekton olması gerekirdi, burada T bir tekil , vs vs olurdu) – Kristof

+0

Eklenen SLaks kodu iyileştirmesi. İlk satır başınızı döndürüyor. –

+0

@Kristof Örneğe bakınız: "public MyClass: Singleton " yukarıdaki.'MyClass' IS-A 'Singleton ' türünde çalışır. Yine de biraz beyin erimesi. –

3

SLaks eklemek gerekir doğrudur - bu şiddetle türetilmiş sınıfa yazıldığında sizin temel sınıfta kodu sağlar istediğinizde genellikle yararlı bir kalıptır.

Ayrıca, genel türün soyut türden miras alması gerektiğini belirtmek için genel bir parametreye genel bir kısıtlama da eklersiniz. Bu kısıtlamanın eklenmesi sözdizimi özyinelemeli, ancak bu konuda panik yapmayın - yinelemeli olarak değerlendirilmez ve yalnızca geçerli genel türlerin türetilmiş sınıflar olmasını sağlar. Örneğin, bir çay ve kahve harmanlama işi yaptığınızı varsayalım. Kahve ile kahve ve çay ile çay karıştırmak için mantıklı, ama kahve ile çay karıştıramazsınız emin olmak istiyorum. Ancak, her ikisi de içecekler olduğundan, onları aynı şekilde modellemek istersiniz. CRTP hakkında okurken

public abstract class Beverage<T> where T : Beverage<T> 
{ 
    public abstract T Blend(T drink1, T drink2); 
} 

public class Tea : Beverage<Tea> 
{ 
    public override Tea Blend(Tea drink1, Tea drink2) 
    { 
     // Blend tea here. 
    } 
} 
public class Coffee : Beverage<Coffee> 
{ 
    public override Coffee Blend(Coffee drink1, Coffee drink2) 
    { 
     // Blend coffee here. Although coffee is nasty, so 
     // why you'd want to is beyond me. 
    } 
} 

, bu C++ şablonları yalnızca C# jenerik yüzeysel benzer olduğunu hatırlamak önemlidir. Temel fark, şablonların etkin bir şekilde derleme zamanında çalışan bir kod oluşturma aracı iken, C# jeneriklerinin çalışma zamanında desteklenmesidir. Ayrıca, bu şekilde yazma kodu okunabilirliği azaltabilir. Bu yüzden, bunun doğru yaklaşımın olacağı kesin örnekler olsa da, çözmeye çalıştığınız sorunu düşünmeli ve daha açık bir yaklaşım olup olmadığını düşünmelisiniz.

+0

MyClass.Instance derler. –

+0

Uygun şekilde düzenlenmiş. –

+2

Tabii ki, "kamu dersi Kahve: İçecek " yasal bir beyannamedir. Bunu dağıtmak kolay. – Brian

İlgili konular