2009-08-24 7 views
7

Bir sorum var. Çerçevede, genellikle jenerikler gelmeden önce yazılmıştır, genellikle farklı türlerde bir şeyler yapmak için çok fazla aşırı yüklenme olan bir işlev görürsünüz.Genel yüklere karşı aşırı yükler

a)

Parse(int data) 
Parse(long data) 
Parse(string data) 
..etc 

her yöntem ve böylece küçük bir kod tutmak yardımcı olarak ok gibi görünüyor Yani. Öte yandan, artık jenerik ile aşağıdakileri yapabilirsiniz:

b)

Parse<T>(T data) 

ve sonra ne tiplerini anlaması için denemek için typeof() ile IFS/switch tabloların çeşit ve onlarla ne yapmalı?

En iyi uygulama nedir? Ya da a) ve b) arasında seçim yapmama yardımcı olacak ideiaslar nelerdir?

+4

En iyi uygulama şudur: _generically_ öğesini uygulayan bir şeyi uygularken _generics_ 'ı kullanın. Belirli bir alternatif alternatife sahip olduğunuzda aşırı yükleme kullanın. –

cevap

18

IMHO, eğer/anahtar ifadeleri gerekiyorsa, daha fazla aşırı yüklemelisiniz. Uygulamanın, yeniden kullanmak için beton tipine bağlı olmadığı durumlarda jenerikler kullanılmalıdır.

genel bir kural olarak Yani: Eğer mümkün olan tüm türleri için çalışan tek uygulama olabilir eğer her tip
  • kullanım jenerik için ayrı uygulama olacaktır

    • aşırı eğer.
  • +1

    Belirli bir davranışa ve türlerin geri kalanı için varsayılan davranışa sahip birkaç türünüz varsa, biraz bulanık olabilir. –

    +0

    Elbette, bu basit vakalar için basit bir kuraldır, ancak her zaman onun kadar basit değildir. Eğer karmaşıklaşırsa, strateji, ziyaretçi ya da herhangi bir şey gibi bir örüntüyü uygulamayı düşünebiliriz. –

    +3

    @John - Diğer her şey için hem "Parse (int data)" hem de diğer belirli türlerde) ve "Parse (T verileri)" seçeneklerine sahip olabilirsiniz. Belirli aşırı yükleme türlerinden biri içeri aktarılırsa, jenerik olmayan yöntem kullanılacaktır, aksi halde tür bağımsız değişken genel yöntemle çıkarılacaktır. – statenjason

    4

    Genetiklerin kullanılmasının bir grup ifs/anahtar deyimiyle sonuçlandığı yerde tanımlamanız, bir desen desenidir.

    Bunun için bir çözüm, jenerik kullanmanıza izin veren bir strateji modeli uygulamaktır, ancak aynı zamanda her farklı durumla nasıl başa çıkılacağını bilmekten Parse yönteminin endişelerini ayırmaktır.

    Örnek:

    class SomeParser 
    { 
        void Parse<T>(ParseStrategy<T> parseStrategy, T data) 
        { 
         //do some prep 
    
         parseStrategy.Parse(data); 
    
         //do something with the result; 
        } 
    } 
    
    class ParseStrategy<T> 
    { 
        abstract void Parse(T data); 
    } 
    
    class StringParser: ParseStrategy<String> 
    { 
        override void Parse(String data) 
        { 
         //do your String parsing. 
        } 
    } 
    
    class IntParser: ParseStrategy<int> 
    { 
        override void Parse(int data) 
        { 
         //do your int parsing. 
        } 
    } 
    
    //use it like so 
    [Test] 
    public void ParseTest() 
    { 
        var someParser = new SomeParser(); 
        someParser.Parse(new StringParser(), "WHAT WILL THIS PARSE TO"); 
    } 
    

    ve sonra size geliştirmek stratejilerin herhangi geçmek mümkün olacaktır. Bu, endişelerinizi birden fazla sınıfta doğru bir şekilde ayırmanıza ve SRP'yi (tek sorumluluk ilkesi.

    1

    ihlal etmemize olanak tanır. Bununla ilgili tek bir kural yoksa, jenerikler belirli bir tür alakasız olduğunda kullanılmalıdır..Yani bu tür kısıtlama olamaz, ancak bu tür aslında aslında önemli değil. Bu durumda, ayrıştırma yöntemi tamamen (her biri için) bağlıdır ve her tür için. burada iyi bir çözüm gibi görünüyor.

    7

    Kod kokusu.

    siz "/geçerseniz çeşit varsa", sadece 'un polimorfizm çığlık verdiği bir kod kokusu. Bu soruna çözümün jeneriklerin olduğunu önermektedir. kodu beton tipine bağlı olmadığında jenerik kullanılmalıdır.

    Bu Google Tech Talks Videosu'nu izleyin: "The Clean Code Talks -- Inheritance, Polymorphism, & Testing". Özellikle ne hakkında konuşuyorsunuz.

    +3

    Yuck ... Okumak zor olan bir şey, programcının tüm şişirilmiş sınıf hiyerarşileriyle mükemmel sıradan ve basit if ifadelerini değiştirmeye çalıştığı koddan çok daha zor. – jalf

    +0

    @jalf Yuck ... Pek çok seçeneğin * daha fazla olması * daha çok seçeneğe bağlı basit if ifadeleri tekrar tekrar tekrar edilir :) Polymorfism kodun yönetilmesine yardımcı olur: yeni bir seçenek sadece Yeni sınıf ve yeni bir yöntem, projedeki tüm kodlarla tam bir arama değil! –

    +0

    @DanibISHOP oh, görüyorum ki, sadece “tekrarlanan ve tekrarlanan” parçayı ince havadan icat ettiniz. Ne yazık ki, yorumumla ya da yorum yaptığım cevapla * alakası yok. Cevap şöyle diyor: * Eğer bir tür if/switch * varsa, bu bir kod kokusu. Tekrarlama hakkında hiçbir şey söylemiyor. – jalf

    2

    Burada bir sorun var - eğer jenerik yapmak için deyim/anahtar ifadesi gerekiyorsa, muhtemelen daha büyük bir sorunla karşılaşırsınız. Bu durumda, genel argümanın EVERY tipi için (doğru bir şekilde) çalışmayacağından, büyük olasılıkla ele aldığınız sabit bir tip kümedir. Bu durumda, belirli türlerin tek tek ele alınabilmesi için aşırı yüklenmeler yapmanız çok daha iyidir.

    Bu

    birçok avantajı vardır: kötüye şansı yoktur

    • - tip uygun olan çok açıktır - Eğer kullanıcı geçersiz bir argüman
    • API'nızdan daha netlik yoktur geçemez konum
    • jenerik yöntemler başlayan kullanıcılar için de bariz daha kullanmak karmaşık ve olmayan
    • jenerik kullanımı herhangi türü geçerli olduğunu göstermektedir - onlar gerçekten her türlü çalışması gerekir
    • Genel yöntem muhtemelen daha yavaş olabilir, performans anlamlı

    Argümanınız herhangi bir türde çalışabiliyorsa, bu durum daha az anlaşılır hale gelir. Bu durumda, genellikle aşırı yüklemeleri ve türler için genel bir geri dönüş yöntemi eklemeyi düşünürdüm. Bu, yönteme "beklenen" bir tür ilettiğinizde bir performans artışı sağlar, ancak diğer beklenmeyen türlerle de çalışabilirsiniz.