2009-04-23 18 views
6

में रीफैक्टरिंग पर मूल प्रश्न यह एक शुरुआती प्रश्न हो सकता है लेकिन क्या व्हील संपत्ति के डुप्लिकेशंस को अमूर्त वर्ग में दोहराए जाने का एक मानक तरीका है, फिर भी पार्ट प्रकार के लिए स्पष्ट कलाकार को अभी भी बनाए रखा है। आइए मान लीजिए कि हमें फास्टकायरहेल को स्लोकर पर डालने से रोकना है, और इस तरह की कई संपत्तियां हैं।एक अमूर्त वर्ग

abstract class Car {} 

class FastCar : Car 
{ 
    public FastCarWheel Wheel { get; set; } 
} 

class SlowCar : Car 
{ 
    public SlowCarWheel Wheel { get; set; } 
} 

abstract class WheelPart {} 

class FastCarWheel: WheelPart {} 

class SlowCarWheel: WheelPart {} 

इस प्रकार के परिदृश्य में इस प्रकार के नकल की अनुमति देना आम बात है? मैं जेनेरिकों का उपयोग करने की सोच रहा था, लेकिन ऐसा लगता है कि मैं इस मुद्दे को चारों ओर ले जा रहा हूं, और यह इस तरह से व्यवहार करने वाली प्रत्येक अतिरिक्त संपत्ति के लिए बदतर हो जाता है।

abstract class Car <P> 
    where P : Part 
{ 
    protected abstract P Wheel { get; set; } 
} 

धन्यवाद

उत्तर

0

एक पहिया इंटरफेस को परिभाषित करें (IWheel):

public interface IWheel 
{ 
} 

FastCarWheel और SlowCarWheel के लिए इंटरफ़ेस को लागू जैसे

public class FastCarWheel : IWheel 
{ 
} 

अब आप अपने अमूर्त वर्ग बन जाता है:

कार की

उपवर्गों तो व्हील की जो कुछ भी कार्यान्वयन वे चुनते उपयोग कर सकते हैं:

FastCar fastCar = new FastCar(); 
fastCar.Wheel = new FastCarWheel(); 
+0

हालांकि यह समस्या है। वह नहीं चाहता कि किसी भी कार के किसी भी प्रकार का पहिया हो। वह फास्टकारों को केवल फास्टविल्स के लिए चाहता है, और स्लोवार्स में केवल स्लोवाइल्स हैं। एक इंटरफ़ेस इसे पूरा नहीं करेगा। – Joseph

+0

यदि फास्टकार में स्लोवायरहेल नहीं हो सकता है, तो वह तर्क FastCar में है, न कि बेस क्लास में। –

+0

मैं सहमत हूं, लेकिन समस्या यह है कि आपका कोड इस के उपयोग को बढ़ावा देगा (fastCar.Wheel = new SlowCarWheel();) जिसे उन्होंने स्पष्ट रूप से कहा था कि वह अनुमति नहीं देना चाहता था। हालांकि, मैं सहमत हूं कि यह तर्क आधार वर्ग में नहीं है। – Joseph

1

मैं एक Fast या Slowpolicy मदद कर सकते हैं (किसी दिए गए कार प्रकार के लिए सही पहिया डाल का उपयोग कर लगता है, जहां दोनों Car और Wheel नीति पर निर्भर हैं और Car ऑब्जेक्ट, पहियों का एक निजी एकत्रीकरण है)।

1

यह समाधान बहुरूपी नहीं है, लेकिन अपने ही एकमात्र विकल्प हो सकता है अगर आप आधार वर्ग स्तर पर दृश्यता की जरूरत है:

abstract class Car 
{ 
    private CarWheel wheel; 
    public CarWheel Wheel 
    { 
     get { return wheel; } 
     protected set { wheel = value; } 
    } 
} 

class FastCar : Car 
{ 
    public new FastCarWheel Wheel 
    { 
     get { return base.Wheel as FastCarWheel; } 
     set { base.Wheel = value; } 
    } 
} 

class SlowCar : Car 
{ 
    public new SlowCarWheel Wheel 
    { 
     get { return base.Wheel as SlowCarWheel ; } 
     set { base.Wheel = value; } 
    } 
} 

यदि आपका आधार वर्ग बहुत ज्यादा कर रही है मूल्यांकन करने के लिए चाहते हो सकता है। अपनी कक्षाओं को कई छोटी कक्षाओं में विभाजित करके अपनी समस्या का समाधान करना संभव हो सकता है। दूसरी तरफ, कभी-कभी यह अपरिहार्य है।

1

मैं एक आईसीएआर बनाने और उसके बाद एक अमूर्त वर्ग के बजाय आपकी कार इस तरह परिभाषित करेंगे

interface ICar 
{ 
    IWheel Wheel {get; set;} 
} 

class FastCar: ICar 
{ 
    FastWheel fastWheel; 
    IWheel Wheel 
    { 
     get { return fastWheel; } 
     set 
     { 
      if (value is FastWheel) fastWheel = (FastWheel)value; 
     }  
    }   
} 

class SlowCar: ICar 
{ 
    SlowWheel slowWheel; 
    IWheel Wheel 
    { 
     get { return slowWheel; } 
     set 
     { 
      if (value is SlowWheel) slowWheel = (SlowWheel)value; 
     }  
    } 
} 

class FastWheel: IWheel {} 
class SlowWheel: IWheel {} 
1

अपने लक्ष्य संपत्ति एक WheelPart के रूप में वापस पाने के लिए ग्राहक कोड की इजाजत दी प्रतीत होता है के बाद से, लेकिन केवल इसे एक विशिष्ट सबक्लास के रूप में सेट करें जिसमें आपके पास कुछ विकल्प हैं। हालांकि मुझे डर है कि उनमें से कोई भी बहुत साफ नहीं है।

सबसे पहले आप एक रनटाइम त्रुटि फेंक सकता है अगर गलत प्रकार सेट है:

public abstract class Car 
    { 
     public abstract WheelPart Wheel { get; set; } 
    } 

    public class FastCar : Car 
    { 
     private FastWheel _wheel; 
     public override WheelPart Wheel 
     { 
      get { return _wheel; } 
      set 
      { 
       if (!(value is FastWheel)) 
       { 
        throw new ArgumentException("Supplied wheel must be Fast"); 
       } 
       _wheel = (FastWheel)value; 
      } 
     } 
    } 

लेकिन मैं ऐसा नहीं होगा के रूप में यह ग्राहक कोड के लिए बहुत स्पष्ट नहीं है कि पहिया के किसी भी अन्य प्रकार एक फेंक जाएगा अपवाद, और उन्हें कोई कंपाइलर प्रतिक्रिया नहीं मिलेगी।

नहीं तो आप संपत्ति के लिए मनुष्य और सेटर को अलग कर सकता है ताकि प्रकार की आवश्यकता बहुत स्पष्ट है:

public abstract class Car 
    { 
     public abstract WheelPart Wheel { get; } 
    } 

    public class FastCar : Car 
    { 
     private FastWheel _wheel; 
     public override WheelPart Wheel 
     { 
      get { return _wheel; } 
     } 

     public void SetWheel(FastWheel wheel) 
     { 
      _wheel = wheel; 
     } 
    } 

यह बहुत ग्राहक और IMHO एक अच्छे समाधान के लिए स्पष्ट करता है, तो आप पूरी तरह बेनकाब करना चाहिए आधार व्हीलपार्ट कक्षा के रूप में गेटटर।

+0

दूसरा समाधान बहुत अच्छा लगता है। – Greg

संबंधित मुद्दे