2010-04-30 12 views
7

क्या सी # में ऐसा करने का कोई तरीका है? मुझे पता है कि सबक्लास अपने स्वयं के कन्स्ट्रक्टर को कॉल करने से पहले सुपरक्लस कन्स्ट्रक्टर को कॉल करेगा, लेकिन अगर मेरे पास सुपरक्लास पर कुछ कोड है जो केवल सभी उपclass रचनाकारों के नाम पर निष्पादित किया जाना चाहिए?सभी उप-वर्गों के निर्माण के बाद मैं सुपरक्लास में कुछ कोड कैसे निष्पादित करूं?

+3

क्या आपके पास एक विशिष्ट उपयोग उदाहरण है? –

उत्तर

3

एक तरह से इस लक्ष्य को हासिल करने के लिए एक 2 चरण निर्माण के लिए जाने के लिए और प्रारंभ करने में किया जाएगा। तो तुम उदाहरणों का निर्माण और फिर एक इनिशियलाइज़ विधि है जो उचित आदेश

class MyBase 
{ 
    // Only if need to do some core initialization 
    public MyBase() 
    { 
    } 

    public virtual Initialize() 
    { 
    // do some initialization stuff here 
    } 
} 

class MyDerived : MyBase 
{ 
    // Only if need to do some core initialization 
    public MyDerived() 
    { 
    } 

    public override Initialize() 
    { 
    // do some initialization stuff here 

    // Call the base class initialization function 
    base.Initialize(); 
    } 
} 
+3

मैं करूंगा एक कारखाने विधि या Asbtract फैक्टरी का उपयोग कर यह सुनिश्चित करें कि प्रारंभ अर्थ विज्ञान सभी कोड में फैला हुआ नहीं कर रहे हैं सलाह देते हैं। – LBushkin

+0

ठीक है, कि वास्तव में नहीं है मैं क्या मतलब है, लेकिन यह थोड़े मुझे समस्या को हल मदद करता है, Ty। –

0
class A : B 
{ 
    public A() : base() 
    { 
     base.doSomething(); 
    } 
} 

class B : C 
{ 
    public B() : base() 
    { 

    } 

    public void doSomething() { /* ... */ } 
} 

class C 
{ 
    public C() { /* ... */ } 
} 

निष्पादन आदेश होना चाहिए:

  1. सी :: ctor()
  2. बी :: ctor()
  3. एक :: ctor()
  4. बी :: DoSomething ()
+0

जैसा कि मैंने कहा था, विधि सुपरक्लास में निष्पादित की जानी चाहिए, उप-वर्ग में नहीं, आप केवल उप-वर्ग में सुपरक्लास विधि को कॉल कर रहे हैं। –

+0

मुझे संदेह है कि ओपी एक समाधान की तलाश में है जहां बेस क्लास यह सुनिश्चित कर सकता है कि प्रकार के बाद कुछ प्रारंभिकता पूरी तरह से चालू हो जाती है। अन्यथा, प्रत्येक व्युत्पन्न वर्ग लेखक को आवश्यक प्रारंभिक तर्क को कॉल करना सुनिश्चित करना होगा। – LBushkin

+0

Thats मैं वास्तव में क्या जरूरत है :( –

0

मुझे यकीन नहीं है कि आपका क्या मतलब है - क्या आप हमारे अंतिम उपclass con के अंत में सुपर क्लास में कोड को कॉल नहीं कर सकते structor? वैकल्पिक रूप से आप इसे तत्काल बाद सीधे कॉल कर सकते हैं।

class Program 
    { 
     static void Main(string[] args) 
     { 
      SubSub obj = new SubSub();     
      //obj.DoStuff(); 
      Console.ReadLine(); 
     } 
    } 

    class Super 
    { 
     public Super() 
     { 
      Console.WriteLine("Constructing Super"); 
     } 
     public void DoStuff() 
     { 
      Console.WriteLine("Doin' stuff"); 
     } 
    } 

    class Sub : Super 
    { 
     public Sub() 
     { 
      Console.WriteLine("Constructing Sub"); 
     } 
    } 

    class SubSub : Sub 
    { 
     public SubSub() 
     { 
      Console.WriteLine("Constructing SubSub"); 
      DoStuff(); 
     } 
    } 

हो जाएगा ताकि उत्पादन:

Constructing Super 
Constructing Sub 
Constructing SubSub 
Doin' stuff 
+0

क्या मेरा मतलब है कि कोड सुपर क्लास में वस्तु का पूरा निर्माण के बाद क्रियान्वित किया जा सकता है, उपवर्ग इसके बारे में आप दो-पास के लिए जाना बनाने/प्रारंभ करते हैं, तो पता नहीं करनी चाहिए। –

3

आप निम्न कर सकता है में आधार वर्ग प्रारंभ लागू फोन, लेकिन यह जोखिम भरा है (नीचे मेरी संपादित देखें):

public class Parent 
{ 
    public Parent() 
    { 
     Initialize(); 
    } 

    protected virtual void Initialize() 
    { 
     // do stuff 
    } 
} 

public class Child : Parent 
{ 
    protected override void Initialize() 
    { 
     // do child stuff 
     base.Initialize(); 
    } 
} 

संपादित

नीचे टेरेंस की टिप्पणी में सुझाव दिया गया है, यह एक जोखिम भरा तरीका है क्योंकि Initialize() से पहले Child के निर्माता निष्पादित किया जाता है निष्पादित किया जाएगा है। यदि Child के निर्माता में कोई फ़ील्ड प्रारंभ हुआ है, तो वे Initialize() द्वारा उपयोग किए जाने पर तैयार नहीं होंगे। यह भ्रमित बग का कारण बन सकता है।

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

यहाँ एक सरल समाधान एक स्थिर कारखाने विधि का उपयोग करता है:

class Program 
{ 
    static void Main() 
    { 
     Child.Create(() => new Child(5)); 
     Console.ReadKey(); 
    } 
} 

public abstract class Parent 
{ 
    protected virtual void Initialize() 
    { 
     Console.Write(" is the number."); 
    } 

    public static TChild Create<TChild>(Func<TChild> childGetter) 
     where TChild : Parent 
    { 
     var child = childGetter(); 
     child.Initialize(); 
     return child; 
    } 
} 

public class Child : Parent 
{ 
    private int _number; 

    public Child(int number) 
    { 
     _number = number; 
    } 

    protected override void Initialize() 
    { 
     Console.Write(_number.ToString()); 
     base.Initialize(); 
    } 
} 
+0

इस आभासी बुला के खिलाफ सिफारिश का उल्लंघन करती है एक कन्स्ट्रक्टर से विधियों। इस विधि से बग को ट्रैक करना मुश्किल हो सकता है। देखें: http://blogs.msdn.com/b/scottwil/archive/2005/01/14/353177.aspx और http : //stackoverflow.com/questions/308061/virtual ization-in-super-class-constructor – Terrence

+0

@Terrence, आपकी टिप्पणी के लिए धन्यवाद। मेरा जवाब अपडेट किया गया। – devuxer

2

आप यह कर देता है कि सी # भाषा में निर्मित कुछ भी नहीं है। हालांकि, एक सृजन पैटर्न का उपयोग कर इसका समर्थन कर सकता है। उदाहरण के लिए, Abstract Factory पैटर्न यहां सहायक हो सकता है। बेस फैक्ट्री यह सुनिश्चित करेगी कि कंक्रीट बच्चे के प्रकार के रूप में इसे तुरंत शुरू करने के बाद नव निर्मित बेस क्लास पर एक विधि कहा जाता है।

+0

क्या आपको पता है कि कैसल विंडसर के पास ऐसा कुछ है या नहीं? –

+0

यह वास्तव में इस तरह की PostSharp (जो आप अब याद दिलाया गया है मुझे मेरे जवाब में शामिल किया गया है चाहिए) के रूप में एक AOP उपकरण का डोमेन है, लेकिन यह विंडसर यह करना संभव हो सकता है। कभी कोशिश नहीं की। – RationalGeek

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