2012-05-24 8 views
6

यदि मैं एक कन्स्ट्रक्टर चाहता हूं जो कि बाल कक्षाओं से केवल पहुंच योग्य है, तो मैं कन्स्ट्रक्टर में protected कुंजी शब्द का उपयोग कर सकता हूं।मैं बेस क्लास द्वारा केवल कन्स्ट्रक्टर को कैसे सुलभ बना सकता हूं?

अब मैं विपरीत चाहता हूं।

मेरे बच्चे वर्ग में एक कन्स्ट्रक्टर होना चाहिए जिसे इसकी बेस क्लास द्वारा एक्सेस किया जा सकता है लेकिन किसी भी अन्य वर्ग से नहीं।

क्या यह भी संभव है?

यह मेरा वर्तमान कोड है। समस्या यह है कि बाल वर्गों में एक सार्वजनिक कन्स्ट्रक्टर होता है।

public abstract class BaseClass 
{ 
    public static BaseClass CreateInstance(DataTable dataTable) 
    { 
     return new Child1(dataTable); 
    } 
    public static BaseClass CreateInstance(DataSet dataSet) 
    { 
     return new Child2(dataSet); 
    } 
} 

public class Child1 : BaseClass 
{ 
    public Child1(DataTable dataTable) 
    { 
    } 
} 

public class Child2 : BaseClass 
{ 
    public Child2(DataSet dataSet) 
    { 
    } 
} 
+4

मुझे यकीन नहीं है कि यह संभव है, विरासत की मेरी समझ के खिलाफ बाल वर्गों के बारे में जानने वाले बेस क्लास –

+1

@DanF आप सही हैं, लेकिन 'चाइल्ड क्लास फैक्ट्री' क्लास जो 'चाइल्ड 1' और ' चाइल्ड 2 सामान्य होगा, और एक ही समस्या होगी। – hvd

उत्तर

3

सवाल का जवाब "नहीं" है

वहाँ ऐसी कोई बात नहीं OOP कि केवल इसके बारे में बेस कक्षा को दिखाई करने के लिए बच्चे को कक्षा निर्माता की अनुमति देने में मौजूद है ...

+0

@ जोन - इसका विकल्प लेकिन बहुस्तरीय विरासत में समाधान नहीं है ... उस मामले पर भी विचार करें .. –

12

मैं लगता है कि आपके पास दो विकल्प हैं:

  1. बच्चे के निर्माता internal बनाएं। इसका मतलब है कि यह एक ही असेंबली में सभी प्रकार से सुलभ होगा, लेकिन यह ज्यादातर मामलों में पर्याप्त होना चाहिए।
  2. आधार वर्ग में नेस्ट बच्चे कक्षाओं करें:

    public abstract class BaseClass 
    { 
        public static BaseClass CreateInstance(DataTable dataTable) 
        { 
         return new Child1(dataTable); 
        } 
    
        private Child1 : BaseClass 
        { 
         public Child1(DataTable dataTable) 
         { 
         } 
        } 
    } 
    

    इस तरह, BaseClass निर्माता का उपयोग कर सकते हैं, लेकिन कोई अन्य बाहर प्रकार है कि (बच्चे वर्ग को देखने या यहाँ तक कि) कर सकते हैं।

+3

+1 नेस्टेड कक्षाओं के लिए –

+2

नेस्टेड कक्षा केवल बेस क्लास के अंदर दिखाई देगी, है ना? यकीन नहीं है कि यह इरादा है। –

+0

@lcfseth, हाँ, अगर आप उन्हें 'निजी' चिह्नित करते हैं। और मुझे लगता है कि यह वही है जो इरादा था (ध्यान दें कि फैक्ट्री विधियां 'बेस क्लास' वापस आती हैं)। – svick

-1

जैसा कि प्रणय राणा ने कहा, यह असंभव है। यदि आप स्पष्ट रूप से समझा सकते हैं कि आप यह क्यों चाहते हैं, और क्यों कोई अन्य तकनीक संभव नहीं है, तो शायद माइक्रोसॉफ्ट सी # डिजाइनटेम इसे सी # के भविष्य के संस्करण में जोड़ना चाहता है।

हालांकि, सी # और भाषा (कई अन्य OO भाषाओं इस संभावना के बिना कई वर्षों के लिए चारों ओर गया है।

+0

मुझे नहीं पता कि सी # के संभावित भविष्य संस्करण के बारे में बात कैसे कर रही है। – svick

3

मुझे लगता है कि मैं सिर्फ अपने आप को द्वारा इसे हल। नेस्टेड वर्गों के साथ svicks समाधान पढ़ने के बाद, मैंने सोचा था कि why not use an protected nested class as an argument?

बाहर से

कोई भी Arg का एक उदाहरण और मेरे बच्चे वर्गों से सार्वजनिक contructors केवल BaseClass द्वारा इस्तेमाल किया जा सकता है, जो Arg<T> उदाहरण बना सकते हैं बनाने के लिए सक्षम है।

public abstract class BaseClass 
{ 
    protected class Arg<T> 
    { 
     public T Value { get; set; } 
     public Arg(T value) { this.Value = value; } 
    } 

    public static BaseClass CreateInstance(DataTable dataTable) 
    { 
     return new Child1(new Arg<DataTable>(dataTable)); 
    } 

    public static BaseClass CreateInstance(DataSet dataSet) 
    { 
     return new Child2(new Arg<DataSet>(dataSet)); 
    } 
} 


public class Child1 : BaseClass 
{ 
    public Child1(Arg<DataTable> arg) : this(arg.Value) { } 
    private Child1(DataTable dataTable) 
    { 
    } 
} 

public class Child2 : BaseClass 
{ 
    public Child2(Arg<DataSet> arg) : this(arg.Value) { } 
    public Child2(DataSet dataSet) 
    { 
    } 
} 
+1

यह 'चाइल्ड 1' को तुरंत 'चाइल्ड 1' के विरुद्ध कैसे सुरक्षित करता है? मैंने सोचा था कि आप अपनी खुद की असेंबली में गलत तात्कालिकताओं के खिलाफ खुद को भी सुरक्षित रखना चाहते हैं? (अन्यथा, एक आंतरिक कन्स्ट्रक्टर का समाधान बहुत आसान है।) – hvd

+0

असल में, क्या सी # सार्वजनिक कन्स्ट्रक्टर पर एक अप्राप्य प्रकार की अनुमति देता है? – hvd

+0

आप सही हैं। यह मुझे एक संकलन समय त्रुटि देता है। –

0

एक आधार निर्माता एक ref पैरामीटर स्वीकार करने को कहकर रन-टाइम में वांछित व्यवहार को लागू कर सकता है, और (नहीं threadsafe) की तरह कुछ कार्य करें:

private int myMagicCounter; 

public DerivedClass makeDerived(whatever) // A factory method 
{ 
    DerivedClass newThing; 
    try 
    { 
    ... do whatever preparation 
    newThing = new DerivedClass(ref myMagicCounter, whatever); 
    } 
    finally 
    { 
    ... do whatever cleanup 
    } 
    return newThing; 
} 

BaseClass(ref int magicCounter, whatever...) 
{ 
    if (magicCounter != myMagicCounter) 
    throw new InvalidOperationException(); 
    myMagicCounter++; 
    if (magicCounter != myMagicCounter) 
    throw new InvalidOperationException(); 
} 

ध्यान दें कि यह करने के लिए एक व्युत्पन्न वर्ग निर्माता कॉल के लिए असंभव हो जाएगा फ़ैक्टरी विधि की तैयारी किए बिना नियंत्रण प्राप्त करें, या कारखाने विधि के सफाई के बिना अपने कॉलर पर नियंत्रण वापस करने के लिए। हालांकि, व्युत्पन्न-श्रेणी के कन्स्ट्रक्टर को आंशिक रूप से निर्मित उदाहरण को बाहरी कोड में पारित करने से रोकने के लिए कुछ भी नहीं होगा, जो फैक्ट्री विधि पर नियंत्रण लौटने से पहले मनमाने ढंग से समय के साथ जो कुछ भी पसंद करता है, वह कर सकता है।

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

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