2012-10-04 53 views
7

में पारित नई वस्तु के संदर्भ में रखें क्या किसी रचनाकार में बनाए गए किसी ऑब्जेक्ट का संदर्भ बनाए रखने का कोई अच्छा तरीका है जिसे कुछ विस्तारित वर्ग के सुपर कन्स्ट्रक्टर को पारित करने की आवश्यकता है (इसे सुपर से सुलभ बनाने के अलावा कक्षा या इसे पैरामीटर के रूप में निर्माता में गुजर रहा है)?सुपर कन्स्ट्रक्टर

मुझे एक उदाहरण के साथ स्पष्टीकरण दें। इस प्रकार

class TestA { 
    TestA(Object foo) {} 
} 

अब फैली इस वर्ग, मैं चाहते हैं: इस वर्ग (जो मैं संशोधित नहीं कर सकते और जो मुझे foo के लिए उपयोग नहीं देता है) ले लो

class TestB extends TestA { 
    Object myCopyOfFoo; 

    TestB() { 
     super(new Object()); 
    } 
} 

है वहाँ myCopyOfFoo में बनाए गए new Object() को स्टोर करने का एक अच्छा तरीका है?

न तो इन तीन विचारों में से एक काम करते हैं:

TestB() { 
    myCopyOfFoo = new Object(); 
    super(myCopyOfFoo); 
} 

(त्रुटि: निर्माता कॉल एक निर्माता में पहले बयान होना चाहिए)

TestB() { 
    super(myCopyOfFoo = new Object()); 
} 

(त्रुटि: एक उदाहरण क्षेत्र myCopyOfFoo का उल्लेख नहीं कर सकते जबकि स्पष्ट रूप से एक कन्स्ट्रक्टर का आह्वान करते हुए)

TestB() { 
    super(makeFoo()); 
} 

Object makeFoo() { 
    myCopyOfFoo = new Object(); 
    return myCopyOfFoo; 
} 

(त्रुटि: मैं एक संदर्भ नहीं दे सकता nstance विधि जबकि स्पष्ट रूप से एक निर्माता)

मुझे लगता है मैं निम्नलिखित कर सकता है लागू है, लेकिन यह न तो धागा सुरक्षित है और न ही सुरुचिपूर्ण है:

static Object tempFoo; 

TestB() { 
    super(tempFoo = new Object()); 
    myCopyOfFoo = tempFoo; 
} 

किसी को भी मेरे लिए एक बेहतर विचार है? और पृथ्वी पर क्यों मेरे पहले दो विचार कानूनी नहीं हैं?

उत्तर

15

कैसे के बारे में:

class TestB extends TestA { 
    Object myCopyOfFoo; 

    // I assume you actually wanted this to take a parameter called foo? 
    // I've left it as per the question... 
    TestB() { 
     this(new Object()); 
    } 

    private TestB(Object copy) { 
     super(copy); 
     myCopyOfFoo = copy; 
    } 
} 

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

संपादित करें: यदि आपका असली स्थिति यह है कि यदि आप किसी मौजूदा पैरामीटर की एक प्रति ले जा रहे हैं, तो यह काम करेगा ...

class ClassB extends ClassA { 
    private final Foo copyOfInput; 

    ClassB(Foo input) { 
     super(input = input.clone()); 
     copyOfInput = input; 
    } 
} 

हालांकि यह बहुत बदसूरत है :(

+0

यह एक अच्छा समाधान है कि वास्तव में मेरे कोड अच्छी तरह से फिट बैठता है, के बाद से मैं पहले से ही वैसे भी कई मामलों में दूसरे निजी निर्माता का उपयोग कर रहा तरह दिखता है। मैं इस जवाब को पहले ही चेक-इन करने का लुत्फ उठा रहा हूं, लेकिन यह अभी भी बहुत सारे कोड की तरह दिखता है।मुझे शक है, लेकिन देखते हैं कि कोई भी छोटा सुझाव है या नहीं। लेकिन पहले से ही धन्यवाद! –

+0

@ मार्कस: मेरे पास एक संभावित सुझाव है यदि आपका * वास्तविक * मामला वास्तव में पहले ही पैरामीटर लेता है, और एक प्रति बनाता है। यदि आपके द्वारा दिया गया कोड वास्तव में प्रतिनिधि है (यानी यह कुछ भी नहीं से नई वस्तु बना रहा है) तो मेरा अन्य सुझाव मदद नहीं करेगा। हालांकि मैं इसे संपादित कर दूंगा। –

0

क्या निम्नलिखित के बारे में:

class TestB extends TestA { 
    Object myCopyOfFoo = new Object(); 

    TestB() { 
     super(myCopyOfFoo); 
    } 
} 

वस्तु केवल जब एक नई वस्तु TestB बनाने, संक्षेप में इस यो क्या करेंगे initialised किया जाएगा आप चाहते हैं?

+1

नहीं, त्रुटि प्राप्त करें "सुपरटेप कन्स्ट्रक्टर को कॉल करने से पहले myCopyOfFoo को संदर्भित नहीं किया जा सकता है" –

+1

इसके साथ दूसरी समस्या यह है कि संकलक myCopyOfFoo को TestB() कन्स्ट्रक्टर में प्रारंभ करने में इनलाइन करेगा। तो, भले ही उसने कोई त्रुटि नहीं डाली, फिर भी यह नए ऑब्जेक्ट की बजाय सुपर() को शून्य के साथ कॉल करेगा। –

1

एक अन्य विकल्प:

public class TestB extends TestA { 

    Object myCopyOfFoo; 

    private TestB(Object foo) { 
     super(foo); 
     myCopyOfFoo = foo; 
    } 

    public static TestB createInstance() { 
     Object foo = new Object(); 
     return new TestB(foo); 
    } 

}