2010-10-06 10 views
18

मुझे पता है कि सी # में रचनाकारों का उत्तराधिकारी होना संभव नहीं है, लेकिन संभवतः ऐसा करने का एक तरीका है जो मैं करना चाहता हूं।सी #: विरासत रचनाकार

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

public Constructor(Parameter p) { 
    base.Init(p); 
} 

कि पूरी तरह से सूखी सिद्धांतों का उल्लंघन! दर्जनों रचनाकारों को बगैर मेरे पास सभी जरूरी चीजें कैसे शुरू की जा सकती हैं?

+2

डीआरवाई सिद्धांतों का उल्लंघन करने से भी बदतर इनवेरिएंट सिद्धांत का उल्लंघन कर रहा है। एक विधि के नाम के रूप में 'इनिट' आम तौर पर एक मजबूत संकेत है कि अमान्य राज्यों में वस्तुएं अनिवार्य रूप से मौजूद हैं जहां केवल एक चीज जो वे अच्छी हैं, वह बग पैदा कर रही है। –

+1

सी # वास्तव में वास्तव में DRY का पालन नहीं करता है। यह परेशान हो सकता है लेकिन ... ईमानदारी से, आप मुझे नहीं बता सकते कि आप 'सार्वजनिक', 'संरक्षित', और 'निजी' टाइप करने से थक गए नहीं हैं? –

+1

@ SlippD.Thompson: यह एक और क्षेत्र है जहां सी ++ वास्तव में आसान भाषाओं की तुलना में कम * शब्दशः है ... पिछली बार मैंने देखा है कि व्युत्पन्न वर्ग में आधार रचनाकारों को उजागर करने के बारे में था। –

उत्तर

47

आपको एक ही कोड के साथ सभी रचनाकारों का भार बनाने की आवश्यकता नहीं है; आप केवल एक बनाते हैं, लेकिन व्युत्पन्न कक्षाएं बेस कन्स्ट्रक्टर को कॉल करती हैं:

public class Base 
{ 
    public Base(Parameter p) 
    { 
     Init(p) 
    } 

    Init(Parameter p) 
    { 
     // common initialisation code 
    } 
} 

public class Derived : Base 
{ 
    public Derived(Parameter p) : base(p) 
    { 

    } 
} 
+1

यही मुझे चाहिए। हालांकि मुझे उन कक्षाओं के लिए रचनाकार बनाना होगा जिनके पास नहीं है, मुझे कोड दोहराना नहीं होगा। – Alex

+1

डाउन-वोट क्यों? –

+1

मेरी इच्छा है कि सी # में सी ++ के उत्तराधिकारी कन्स्ट्रक्टर की तरह कुछ हो, फिर भी सभी बेस कन्स्ट्रक्टर –

7

बदलें यह करने के लिए init समारोह आधार वर्ग के लिए निर्माता है, और उसके बाद इस तरह विरासत में मिला वस्तुओं से यह कहते हैं:

public InheritedObject(Parameter p) : base(p) 
{ 
} 

आधार निर्माता निर्माता ही चलाता है में किसी भी कोड से पहले सक्रिय किया जाएगा ।

2

ऐसा कुछ?

public Constructor(Parameter p) : base(p) { 

} 

और आधार वर्ग:

public Base(Parameter p) 
{ 
    Init(p); 
} 

तुम भी, आभासी रूप में अपने Init विधि चिह्नित कर सकते हैं ताकि आप अपने अन्य वर्गों में कुछ मीठा ओवरराइड कर सकते हैं, तो हो सकता है की जरूरत है! ;)

public virtual void Init() { } 

और अपने अन्य वर्गों में:

public override void Init() { base.Init(); //Do other stuff } 
+2

पर कॉल करना अभी भी परेशान है, हालांकि आपको एक कन्स्ट्रक्टर से वर्चुअल विधि को कॉल करने के लिए बहुत सावधान रहना होगा - उपclass 'कन्स्ट्रक्टर तब नहीं चला होगा जब ओवरराइड विधि को कॉल किया जाता है superclass द्वारा, तो सदस्य चर आदि शुरू नहीं किया गया था। – thecoop

+0

सच :) लेकिन आपको वह समस्या वास्तव में जल्दी मिल जाएगी .. – Arcturus

+1

आभासी init विधि व्यर्थ लगता है, यद्यपि। Normaly आपको रचनाकारों में काम करने से बचना चाहिए, और केवल उन्हें प्रारंभ करने के लिए उपयोग करना चाहिए, और यदि यह केवल प्रारंभिक है, तो केवल कन्स्ट्रक्टर का उपयोग क्यों न करें? – AHM

5

एक ही रास्ता base.Init कॉल दोहराना नहीं करने के बजाय आधार निर्माता

class Base 
{ 
    public Base(Parameter p) 
    { 
    this.Init(p) 
    } 

    private void Init(Parameter p) 
    { 
     ... 
    } 
} 

class Inherited : Base 
{ 
    public Inherited(Parameter p) 
    : base(p) 
    { 
     // other constructor logic, but Init is already called. 
    } 
} 
3

आप वारिस नहीं कर सकते हैं कॉल करने के लिए है रचनाकार लेकिन आप उन्हें अपने व्युत्पन्न बच्चों के रचनाकारों से बुला सकते हैं। यदि आप बेस क्लास डिफॉल्ट कन्स्ट्रक्टर निजी बनाते हैं तो यह आपको हर बार व्युत्पन्न कक्षा बनाने के लिए बेस कंस्ट्रक्टर का चयन करने के लिए मजबूर करेगा।

class A 
{ 
    protected A(int x) 
    { 

    } 
} 
class B : A 
{ 
    B(int x) 
     : base(x) 
    { 

    } 
}