2009-09-28 14 views
5

जो मैंने सीखा है, उससे कोई अच्छा नहीं है यदि आप अक्सर कक्षा पदानुक्रमों में डाउनकास्टिंग का उपयोग करते हैं। मैं इसके साथ सहमत हूं, लेकिन अगर इस नियम से कोई अपवाद है तो क्या?
यह वह जगह है जहां ग्राफिकल संपादक का मेरा डिजाइन पतला दिखाता है: मेरे पास दो पदानुक्रम हैं, जहां ज्यामितीय आंकड़े पदानुक्रम ग्राफिक प्राइमेटिव्स से decoupled। इस तरह:
कक्षा पदानुक्रम में हमेशा बुराई हमेशा बुराई है?

public class GeometricPrimitive {...} 
public class RectangeGeometric: Geometric Primitive {...} 
public class GraphicPrimitive {...} 
public class Rectangle: GraphicPrimitive { 
private RectangleGeometric figure; 
... 
} 

तो, हर ठोस ग्राफिक आंकड़ा वर्ग ठोस ज्यामिति वर्ग के उदाहरण समाहित।
क्या यह दृष्टिकोण सही है, या मुझे अधिक सामान्य पसंद करना चाहिए? - दुर्भाग्य से, downcasting इस मामले में इस्तेमाल किया जाएगा:

public class GraphicPrimitive { 
    protected GeometryPrimitive figure; 
    .... 
} 

public class Rectangle: GraohicPrimitive { 

     public Rectangle(Color c, TwoDPoint leftHighPoint, TwoDPoint rightLowPoint): 
      base(new RectangleGeometric(leftHighPoint.Point2D, rightLowPoint.Point2D), c) { } 

     #region Geometric Properties 

     public TwoDPoint LeftTopCorner { 
      get { return new TwoDPoint(base.color, (base.figure as RectangleGeometric).LeftTopCorner); } 
     } 

     public TwoDPoint RightBottomCorner { 
      get { return new TwoDPoint(base.color, (base.figure as RectangleGeometric).RightBottomCorner); } 
     } 

उत्तर

4

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

मैं रिश्ते को जियोमेट्रीप्रिमेटिव और ग्राफिकप्रिमेटिव में बदलकर शुरू करूंगा। मैं जियोमेट्रीप्रिमेटिव पदानुक्रम को डोमेन ऑब्जेक्ट्स के रूप में देखता हूं जो आपके सार दृश्य ग्राफ और ग्राफ़िकप्रिमेटिव पदानुक्रम को निम्न स्तर के दृश्य घटकों के रूप में बनाते हैं जो किसी ज्यामितिप्रिमेट को किसी प्रकार के ग्राफिक्स संदर्भ पर चित्रित करने के लिए उपयुक्त पिक्सेल के सेट में अनुवाद करते हैं। ज्यामितिप्रिमेटिव उप-वर्गों में स्वयं को वर्णन करने के लिए आवश्यक सभी राज्य जानकारी होती है लेकिन उस वर्णन को पिक्सेल में अनुवाद करने के लिए कोई तर्क नहीं है। ग्राफ़िकप्रिमेटिव सबक्लास में सभी पिक्सेल पुशिंग तर्क हैं, लेकिन कोई आंतरिक स्थिति नहीं है। असल में, ग्राफिकप्रिमेटिव पदानुक्रम Command Objects का पदानुक्रम दर्शाता है।

ज्यामिति प्राइमेटिव बेस क्लास में, GetGraphicPrimitive() नामक एक अमूर्त विधि शामिल करें। ग्राफ़िकप्रिमेटिव बेस क्लास में ड्रा (ग्राफिक्स जी) नामक एक अमूर्त विधि शामिल है।

प्रत्येक ज्यामिति प्राइमेटिव के भीतर, ऑब्जेक्ट को खींचने के लिए उचित ग्राफिकप्रिमेटिव और इसे एक्सेस करने के लिए एक्सेसर विधि शामिल करें। पूरे दृश्य को आकर्षित करने के लिए, ज्यामितिप्रिमेटिव ऑब्जेक्ट्स की अपनी संरचना पर चलें, प्रत्येक को अपने ग्राफिकप्रिमेटिव के लिए पूछें और फिर ड्रा() विधि का आविष्कार करें।

abstract class GeometryPrimitive 
{ 
    public abstract GraphicsPrimitive GetGraphicsPrimitive(); 
} 

abstract class GraphicsPrimitive 
{ 
    public abstract void Draw(Graphics g); 
} 

class RectangleGeometryPrimitive : GeometryPrimitive 
{ 
    public Point TopLeft {get; set;} 
    public Point BottomRight {get; set;} 

    private RectangleGraphicPrimitive gp; 

    public RectanglePrimitive(Point topLeft, Point bottomRight); 
    { 
     this.TopLeft = topLeft; 
     this.BottomRight = bottomRight; 
     this.gp = new RectangleGraphicsPrimitive(this); 
    } 

    public GraphicsPrimitive GetGraphicsPrimitive() 
    { 
     return gp; 
    } 
} 

class RectangleGraphicsPrimitive : GraphicsPrimitive 
{ 
    private RectangleGeometryPrimitive p; 

    public RectangleGraphicsPrimitive(RectangleGeometryPrimitive p) 
    { 
     this.p = p; 
    } 

    public void Draw(Graphics g) 
    { 
     g.DrawRectangle(p.TopLeft, p.BottomRight); 
    } 
} 

class CircleGeometryPrimitive : GeometryPrimitive 
{ 
    public Point Center {get; set;} 
    public int Radius {get; set;} 

    private CircleGraphicPrimitive gp; 

    public RectanglePrimitive(Point center, int radius); 
    { 
     this.Center = center; 
     this.Radius = radius; 
     this.gp = new CircleGraphicsPrimitive(this); 
    } 

    public GraphicsPrimitive GetGraphicsPrimitive() 
    { 
     return gp; 
    } 
} 

class CircleGraphicsPrimitive : GraphicsPrimitive 
{ 
    private CircleGeometryPrimitive p; 

    public CircleGraphicsPrimitive(CircleGeometryPrimitive p) 
    { 
     this.p = p; 
    } 

    public void Draw(Graphics g) 
    { 
     g.DrawCircle(p.Center, p.Radius); 
    } 
} 

आप ऊपर देख सकते हैं, कोई downcasting स्क्रीन करने GeometryPrimitives आकर्षित करने के लिए आवश्यक है।विरासत के उचित उपयोग के साथ, आप विभिन्न ज्यामिति प्राइमेटिव के बीच ग्राफिक्स प्राइमेटिव ऑब्जेक्ट्स भी साझा कर सकते हैं। उदाहरण के लिए, स्क्वायरजीमेट्रीप्रिमेटिव और आयतगेटोमेट्रीप्रिमेटिव दोनों आयतगणग्राफिक्सप्रिमेटिव का उपयोग कर सकते हैं यदि स्क्वायरजीमेट्रीप्रिमेट आयताकार जीमेट्रीप्रिमेटिव से निकलती है।

+0

मैंने आपके रास्ते का पालन किया, धन्यवाद – chester89

+0

मुझे खुशी है कि यह आपके लिए काम करता है :) –

2

आप कई जानकारी दे नहीं है, इसलिए मैं वास्तव में क्या यह दो पदानुक्रम के लिए पर्याप्त है के बारे में मेरी राय दे सकते हैं। हम सब इस समानांतरवाद की लागत पता है, लेकिन केवल आप लाभ का मूल्यांकन कर सकते हैं ...


मैं अपने प्रोग्रामिंग भाषा नहीं जानता। लेकिन आपके द्वारा उल्लिखित डाउनकास्टिंग से बचने के लिए एक आम समाधान है, बेस क्लास पैरामीटर प्रकार (जेनेरिक या टेम्पलेटिंग कहा जाता है) का उपयोग कर। यह जावा, सी ++ और कई आधुनिक भाषाओं में काम करता है।

विचार यह है कि फ़ील्ड का सटीक प्रकार base.figure प्रत्येक उपclass द्वारा निर्धारित किया जाता है। बेस क्लास में आप जो जानते हैं वह यह है कि यह GeometryPrimitive का उप प्रकार टी है। प्रत्येक उपclass में, आपने सटीक प्रकार RectangleGeometric परिभाषित किया है जो टी को प्रतिस्थापित करता है, इसलिए इस सबक्लास के भीतर प्रकार सटीक है।

जावा उदाहरण:

public GraphicPrimitive<T extends GeometryPrimitive> { 
     protected T figure; 
    } 

    public Rectangle extends GraohicPrimitive<RectangleGeometric> { 
     // It appears in this class that the field was defined as 
     //protected RectangleGeometric figure; 

     public TwoDPoint getLeftTopCorner { 
     return new TwoDPoint(base.color, figure.LeftTopCorner); 
     } 
    } 
+0

+1 मैं इस के साथ जाऊंगा, यह स्पष्ट रूप से संकलित समय पर व्यक्त करता है कि आप इस वर्ग के उपयोगकर्ता को परिभाषित करना चाहते हैं कि यह किस विशिष्ट वर्ग का उपयोग करेगा। – eglasius

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