2010-06-18 6 views
7

सी # में, मेरे पास शीर्ष के पास कुछ सार आधार वर्गों और व्युत्पन्न कक्षाओं की एक उचित संख्या के साथ एक श्रेणी पदानुक्रम है। इन कंक्रीट कक्षाओं में कुछ सामान्य गुण और विधियां हैं जो समान रूप से कार्यान्वित की जाती हैं। यह मुझे अपर्याप्त के रूप में मारता है और इसलिए एक सामान्य सार वर्ग में इस सामान्य व्यवहार को लागू करने के लिए एक समाधान हो सकता है।अमूर्त आधार कक्षाओं के विकल्प में आम व्यवहार को लागू करें?

abstract class Control; 

abstract class SquareControl: Control 
{ 
    public int SquarishProperty; 
    public void SquarishMethod(); 
}; 

class Window: SquareControl; 
class Button: SquareControl; 

हालांकि, क्या हुआ अगर पदानुक्रम में कई अन्य वर्गों कुछ अन्य व्यवहार साझा लेकिन यह भी एक और आधार वर्ग से नियंत्रणों में से एक के साथ आम में कुछ साझा? शायद समानता के बहुत सारे क्षेत्र हैं। अमूर्त बेस क्लास कार्यान्वयन के साथ इसे मॉडल करने के लिए अव्यवहारिक हो जाएगा?

abstract class FlashableControl: Control 
{ 
    public int FlashyProperty; 
    public void FlashMethod(); 
}; 

class StatusBar: FlashableControl; // but it's also a bit square too, hmm... 

तो आप कक्षाओं के बिना कक्षाओं में ऐसे कार्यान्वयन को साझा करने के बारे में कैसे जाते हैं?

मुझे लगता है कि मैं एक इंटरफ़ेस के कार्यान्वयन को किसी अन्य वर्ग में प्रतिनिधि बनाना चाहता हूं और उस कक्षा में वांछित कक्षाओं की ओर से उन गुणों और विधियों को लागू करना है, ताकि उपयोगकर्ता को स्टेटसबार और विंडो मानक इंटरफ़ेस का समर्थन करने के लिए दिखाई दे , लेकिन कवर के तहत यह कुछ और है जो इसे लागू करता है।

मैं इस व्यवहार को लागू करने वाले समेकित वर्गों को कल्पना कर सकता हूं, लेकिन क्या यह उचित है और क्या कोई नुकसान है? विकल्प क्या हैं?

धन्यवाद

+0

FlashMethod, SquarishProperty आदि, क्या उनके पास बेस क्लास में ठोस अपूर्णताएं हैं, या वे सार हैं? – SWeko

+0

यहां वे सार तत्व हैं जो मैं नहीं करना चाहता हूं, वास्तविक कार्यान्वयन में मेरे पास कई व्युत्पन्न कक्षाएं हैं जिनमें से कुछ समान कार्यान्वयन साझा करते हैं, न केवल इंटरफ़ेस, बल्कि वास्तविक कोड (गुण और विधियां) समान हैं। – DaBozUK

उत्तर

3

आप इस प्रकार का पैटर्न का उपयोग कर सकते हैं:

public interface ICommonServices 
{ 
    string SomeProperty { get; set; } 

    void SomeMethod(string param); 
} 

public static class CommonServiceMethods 
{ 
    public static void DoSomething(this ICommonServices services, string param) 
    { 
     services.SomeMethod(services.SomeProperty + ": " + param + " something extra!"); 
    } 
} 

सभी वर्गों कि ICommonServices लागू अब भी विस्तार विधि है, जो सभी ICommonServices कार्यान्वयन द्वारा उजागर उन सुविधाओं पर निर्भर करता है के माध्यम से कुछ नि: शुल्क व्यवहार मिलता है। यदि आपको बेस क्लास कार्यक्षमता तक पहुंच की आवश्यकता है, तो आप इसे अपने इंटरफ़ेस में डाल सकते हैं और आईसीओएमओएन सर्विसेज भी उस इंटरफ़ेस को कार्यान्वित कर सकते हैं। अब आप एकाधिक आधार वर्गों का उपयोग किए बिना इंटरफेस के लिए 'डिफ़ॉल्ट' एक्सटेंशन कार्यक्षमता बना सकते हैं।


संपादित

आप इन तरीकों में से कुछ आंतरिक होना चाहते हैं, तो आप इस तरह के पैटर्न को बदल सकते हैं

public class MyObject : IServices 
{ 
    public string PublicProperty { get; private set; } 

    string IServices.SomeProperty { get; set; } 

    void IServices.SomeMethod(string param) 
    { 
     //Do something... 
    } 
} 

public interface IPublicServices 
{ 
    string PublicProperty { get; } 
} 

internal interface IServices : IPublicServices 
{ 
    string SomeProperty { get; set; } 

    void SomeMethod(string param); 
} 

internal static class ServiceMethods 
{ 
    public static void DoSomething(this IServices services, string param) 
    { 
     services.SomeMethod(services.SomeProperty + ": " + param + " something extra!"); 
    } 
} 

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

+0

माइक्रोसॉफ्ट यूनिटी आईओसी कंटेनर भी इस चाल का उपयोग करता है। –

+0

यह दृष्टिकोण मुझे वास्तव में पसंद है और इसे लागू करने के लिए एक जाना होगा। क्लाइंट कोड से अन्य असेंबली में इस वर्ग को छुपाने का सबसे अच्छा तरीका क्या है? Boz – DaBozUK

+0

@DaBozUK, मैंने केवल एक आंतरिक नोट –

3

आप इस्तेमाल कर सकते हैं 'है-एक' के बजाय 'एक है' और एक आंतरिक वर्ग नियंत्रण

class Window : Control, ISquareControl 
    { 
     private SquareControl square; 

     public void SquareOperation() 
     { 
      square.SquareOperation(); 
     } 
    } 

    class SquareControl : Control, ISquareControl 
    { 
     public void SquareOperation() 
     { 
      // ... 
     } 
    } 
+0

यह एकत्रीकरण दृष्टिकोण के साथ मुझे बहुत कुछ था, और मुझे लगता है कि मैं स्क्वायरकंट्रोल कक्षा को आंतरिक रखना चाहता हूं ताकि यह विंडो के उपयोगकर्ताओं से छिपा हुआ हो। क्या इस दृष्टिकोण, सीमाएं या गठिया के साथ कोई समस्या है? – DaBozUK

0

एक तरह से इंटरफेस और आधार वर्ग का उपयोग करने के लिए है करने के लिए प्रतिनिधि।

फ्लैशबल कक्षा के बजाय एक अच्छा इंटरफेस बना देगा।

+0

इंटरफ़ेस और बेस क्लास जो मैंने ऊपर वर्णित किया है वह काफी है जो मैं टालना चाहता था। समस्या यह है कि वर्ग पदानुक्रम गन्दा हो सकता है अगर कक्षाओं के कई अलग-अलग सेट कुछ साझा करते हैं लेकिन सभी व्यवहार नहीं करते हैं। – DaBozUK

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