2010-08-02 9 views
7

मैं एक अमूर्त वर्ग है BaseItem इस तरह की घोषणा की:का उपयोग जेनरिक

public abstract class BaseItem 
{ 
    public BaseItem Parent { get; protected set; } 
    public List<BaseItem> Children = new List<BaseItem>(); 

    public abstract string Function1();   
} 

असल में, मैं जहां प्रत्येक आइटम एक माता पिता है कि एक विशिष्ट प्रकार के हो जाएगा है एक डिजाइन को लागू करने के कोशिश कर रहा हूँ और बच्चे जो एक अलग प्रकार के होंगे।

उदाहरण के लिए, आइटमए में बच्चे के सभी आइटम प्रकार होंगे। फिर आइटमबी में आइटमए प्रकार और बच्चों के सभी आइटम आइटम के माता-पिता होंगे। आइटमसी में आइटमबी के माता-पिता और आइटम डी प्रकार के बच्चे होंगे।

मैंने सोचा कि यह अनावश्यक जानवरों से बचने के लिए जेनेरिक का उपयोग करके ऐसा करने के लिए बेहतर होगा क्योंकि मुझे पता है कि माता-पिता और बच्चे मेरे विरासत में से प्रत्येक के लिए किस प्रकार के होंगे। तो मैं इस तरह से कुछ आया:

public abstract class AbstractBase 
{ 
    public abstract string Function1(); 
} 

public abstract class BaseItem<T1, T2> : AbstractBase 
    where T1 : AbstractBase 
    where T2 : AbstractBase 
{ 
    public T1 Parent { get; protected set; } 
    public List<T2> Children = new List<T2>(); 
} 

public class ItemA : BaseItem<ItemA, ItemB> 
{ 
} 
public class ItemB : BaseItem<ItemA, ItemC> 
{ 
} 
public class ItemC : BaseItem<ItemB, ItemD> 
{ 
} 
public class ItemD : BaseItem<ItemC, ItemD> 
{ 
} 

तो दो चीजें। 1. क्या यह एक अच्छा डिजाइन है? क्या ऐसा करने का एक आसान/बेहतर तरीका है? मुझे जेनेरिक का उपयोग करने में सक्षम होने के लिए वास्तव में एक दूसरा सार आधार वर्ग का उपयोग करना पसंद नहीं है। 2. यदि मैं इसे रखता हूं, तो सिरों को संभालने का सबसे अच्छा तरीका क्या है? (यानी ItemA मेरी वास्तविक समस्या डोमेन एक माता पिता नहीं है, लेकिन यह संकलन करने एक माता पिता की जरूरत है। ItemD बच्चे हैं नहीं है, लेकिन मैं इसे कुछ देने की आवश्यकता)

+0

यह सवाल मुझे FORTRAN का उपयोग करना चाहता है। – iandisme

+0

आपके कोड उदाहरण में 'पब्लिक क्लास आइटमसी: बेसइटम <आइटमबी, आइटमसी> 'है, लेकिन संभवतः आप' पब्लिक क्लास आइटमसी: बेसइटम <आइटमबी, आइटमडी> ' का अर्थ है। –

उत्तर

1

यदि मैं आपको सही समझता हूं, तो आप कह रहे हैं कि ItemA में कभी माता-पिता नहीं हैं और ItemD कभी भी कोई बच्चा नहीं है, है ना? ईमानदारी से कहूं तो मैं शायद सिर्फ अलग वर्ग को अपने स्वयं के माता-पिता/बच्चों सही प्रकार के गुणों के साथ घोषणा करेंगे:

public abstract class AbstractBase 
{ 
    public abstract string Function1(); 
} 

public class ItemA : AbstractBase 
{ 
    public List<ItemB> Children = new List<ItemB>(); 
} 
public class ItemB : AbstractBase 
{ 
    public ItemA Parent { get; protected set; } 
    public List<ItemC> Children = new List<ItemC>(); 
} 
public class ItemC : AbstractBase 
{ 
    public ItemB Parent { get; protected set; } 
    public List<ItemD> Children = new List<ItemD>(); 
} 
public class ItemD : AbstractBase 
{ 
    public ItemC Parent { get; protected set; } 
} 

केवल एक चीज आप यहाँ दोहरा रहे हैं Parent और Children संपत्ति/क्षेत्र है। अन्य सभी सामान्य कार्यक्षमता जिन्हें आप AbstractBase में कार्यान्वित कर सकते हैं। (बेशक, उस कार्यक्षमता को माता-पिता/बच्चों तक पहुंच की आवश्यकता होती है - लेकिन फिर आप अपने समाधान में भी एक वर्ग में वापस आ जाते हैं।)

+0

दोनों के डिफ़ॉल्ट कार्यान्वयन को इंजेक्ट करने के लिए हमेशा IoC/DI का उपयोग कर सकते हैं, अंत में, काम करने के लिए जेनेरिक प्राप्त करने के लिए बहुत अधिक ओवरहेड है इससे कोई फर्क नहीं पड़ता कि मैं इसे किस तरह से करता हूं, लेकिन थोड़ा लाभ के लिए। –

0

आप दो सामान्य इंटरफेस, ChildOf<T> और IList<T> उपयोग कर सकते हैं । यह आपको अंतिम मामलों को संभालने देगा। दुर्भाग्य से चूंकि .NET में एकाधिक विरासत नहीं है, इसलिए आप कार्यान्वयन को साझा करने में सक्षम नहीं होंगे।

वैकल्पिक रूप से आप अंत मामलों के लिए अमूर्त वर्ग और एक मार्कर प्रकार इस्तेमाल कर सकते हैं (System.Void आदर्श होगा, लेकिन मुझे नहीं लगता कि यह संकलन होगा), और Parent/Children गुणों से इसके लिए जाँच करें और एक अपवाद फेंक ।

+0

आप इंटरफ़ेस – STW

0

यह बहुत बुरा विचार नहीं लग रहा है, हालांकि ईमानदार होने के लिए मैं मूल समाधान रखने और कास्टिंग के साथ रखकर लुभाना चाहता हूं क्योंकि इससे बहुत अधिक लाभ नहीं होता है। (हालांकि मुझे यह स्वीकार करना होगा कि जब भी मैं कर सकता हूं तो जेनरिक के साथ कास्टिंग को प्रतिस्थापित करने का प्रयास करता हूं)।

आप इसे रखने के लिए कुछ सुझाव चाहते थे:

  • एक अंतरफलक
  • कुछ समाप्त होता है (उदाहरण के लिए दो अतिरिक्त BaseItems जो एक माता पिता और एक बच्चे सामान्य ले के लिए अलग करना के रूप में AbstractBase है प्रकार)।

जाहिर है, यह दूसरा बिंदु केवल जटिलता को जोड़ता है, जो एक और कारण है, मुझे यकीन नहीं है कि यह सार्थक है।

1

मैं इसे इस तरह करना होगा:

public interface IChildOf<T> { 
    T Parent { get; set; } 
} 

public interface IParent<T> { 
    List<T> Children { get; set; } 
} 

//This class handles all of the cases that have both parent and children 
public abstract class BaseItem<T1, T2> : IParent<T1>, IChildOf<T2> 
{ 
    public List<T1> Children { get; set; } 
    public T2 Parent { get; set; } 
} 

//This class handles the top level parent 
public class ItemA : IParent<ItemB> 
{ 
    public List<ItemB> Children { get; set; } 
} 
public class ItemB : BaseItem<ItemC, ItemA> 
{ 
} 
public class ItemC : BaseItem<ItemD, ItemB> 
{ 
} 
//.... as many intermediates as you like. 

//This class handles the bottom level items with no children 
public class ItemD : IChildOf<ItemC> 
{ 
    public ItemC Parent { get; set; } 
} 
0

मैं चीजों को इस तरह से कर रही है के साथ एक समस्या नहीं दिख रहा है, जब से तुम एक विशिष्ट पदानुक्रम है कि शीर्ष स्तर के आइटम की आवश्यकता है प्रकार का होना करने के लिए दिखाई देते हैं ItemA, 2 स्तर के आइटम प्रकार ItemB, आदि का होना

जड़ और पत्र-गांठ करने के लिए, मैं शायद अलग वर्ग वह भी AbstractBase से निकाले जाते हैं निर्धारित करेंगे:

public abstract class RootItem<T2> : AbstractBase 
    where T2 : AbstractBase 
{ 
    public List<T2> Children = new List<T2>(); 
} 

public abstract class LeafItem<T1> : AbstractBase 
    where T1 : AbstractBase 
{ 
    public T1 Parent { get; protected set; } 
} 

public class ItemA : RootItem<ItemB> 
{ 
} 
public class ItemB : BaseItem<ItemA, ItemC> 
{ 
} 
public class ItemC : BaseItem<ItemB, ItemD> 
{ 
} 
public class ItemD : LeafItem<ItemC> 
{ 
} 
संबंधित मुद्दे