2011-10-25 16 views
6

मैं जावा में निम्न उदाहरण श्रेणियां होती हैं:सुपरटेप कन्स्ट्रक्टर को सीधे कॉल नहीं कर सकता - क्यों नहीं?

public class A { } 

public class Super { 
    protected Super() { } 
    public Super(A a) { } 
} 

public class Sub extends Super { } 

public class Consumer { 
    public Consumer() { 
     Sub sub = new Sub(new A()); //compiler error 
    } 
} 

संकलक त्रुटि कहा गया है कि बहस उप में डिफ़ॉल्ट निर्माता है, जो पूरी तरह से समझा जा सकता है के लिए लागू नहीं किया जा सकता।

जो मैं इस बारे में उत्सुक हूं, इस निर्णय के पीछे तर्क है। जावा Sub में डिफ़ॉल्ट खाली कन्स्ट्रक्टर उत्पन्न करता है; इस मामले में इसे दृश्यों के पीछे क्यों नहीं बुलाया जा सकता है? क्या यह मुख्य रूप से सेन हैंड होल्डिंग का मामला है, या क्या कोई तकनीकी कारण है?

संपादित

मुझे पता है कि यह एक भाषा सीमा है हूँ। मैं के बारे में उत्सुक हूं क्यों यह एक भाषा सीमा है।

संपादित 2

ऐसा लगता है कि, जैसा कि अक्सर मामला है, मैं भी कोड मैं वास्तव में बड़ी तस्वीर देखने की में काम कर रहा था के करीब था। मैंने नीचे दिए गए उत्तरों में एक काउंटर-उदाहरण पोस्ट किया है जो दिखाता है कि यह एक खराब बात क्यों है।

+0

मैं कल्पना में पाया कि यह नहीं किया जा सकता है। Http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.2 –

+1

इस बारे में कोई स्पष्टीकरण नहीं है कि यहां जॉन स्कीट का अधिग्रहण है http://stackoverflow.com/questions/1644317/java -कॉन्स्ट्रक्टर-विरासत/1644410 # 1644410 –

+1

मैं आपके संपादन के बारे में उलझन में हूं। आप सोच रहे हैं कि, जब आप एक तर्क के साथ एक कन्स्ट्रक्टर को कॉल करते हैं, तो किसी भी तर्क के साथ एक डिफ़ॉल्ट कन्स्ट्रक्टर को इसके स्थान पर नहीं कहा जा सकता है? स्पष्ट रूप से प्रोग्रामर एक कन्स्ट्रक्टर को कॉल करने की कोशिश नहीं कर रहा था जो पूरी तरह से अपने पैरामीटर को अनदेखा कर देगा, अन्यथा वह पैरामीटर निर्दिष्ट नहीं करता! –

उत्तर

2

मुझे लगता है कि यह दोनों पठनीयता का मुद्दा है और इरादा नहीं मानता है। आप कहते हैं

जावा डिफ़ॉल्ट खाली कन्स्ट्रक्टर उत्पन्न करता है; इस मामले में इसे दृश्यों के पीछे क्यों नहीं बुलाया जा सकता है?

फिर भी मेरे लिए, यह बहुत अधिक समझ बनाने के जावा परोक्ष Super(A) निर्माता "पर्दे के पीछे" कॉल करने के लिए की तुलना में Super() निर्माता कॉल करने के लिए, A अनदेखी करेंगे।

और वहां आपके पास है। इस मामले में क्या होना चाहिए (या ) के बारे में हमारे पास पहले से ही दो अलग-अलग धारणाएं हैं।

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

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

+0

अच्छे अंक, लेकिन आपने मेरे बयान को गलत समझा है। मैं इसे और अधिक स्पष्ट करने के लिए इसे अपडेट कर दूंगा। यह आपके तर्क को बदल नहीं सकता है ... – arootbeer

2
public class Sub extends Super { } 

में निर्माता उप (ए ए) नहीं है, इसमें केवल डिफ़ॉल्ट कन्स्ट्रक्टर उप() है।

रचनाकारों को विरासत में नहीं मिला है।

+0

रचनाकार विरासत में हैं इसलिए यही काम नहीं करता है। – mikek3332002

+0

@ mikek3332002: मुझे लगता है कि हम केवल उप वर्ग से सुपर क्लास कन्स्ट्रक्टर का आह्वान कर सकते हैं लेकिन विरासत में नहीं। –

0

आपने डिफ़ॉल्ट सार्वजनिक कन्स्ट्रक्टर को ओवरराइड कर दिया है, इसलिए कॉल करने के लिए कुछ भी नहीं है।

तो वर्ग उप

public class Sub extends Super 
{ 
    protected Sub(){} 
    public Sub(A a) { } 
} 

के बराबर है यह होगा क्योंकि इसके

  • साने व्यवहार - के रूप में प्रोग्रामर द्वारा निर्दिष्ट, और यह भी OOP भाषाओं
  • में विरासत की अवधारणा इस प्रकार बर्ताव करता है
  • इसके सी ++ विरासत
2

बेस क्लास को टी की आवश्यकता है ओ ऑब्जेक्ट को ठीक से तुरंत चालू करने के लिए सुपर कन्स्ट्रक्टर को कॉल करें। मिसाल के तौर पर विचार करें:

class Super { 
    final String field1; 

    public Super(String field1) { 
     this.field1 = field1; 
    } 
    ... 
} 


class Base extends Super { 
    final String field2; 

    public Base(String field2) { 
     this.field2 = field2; 
    } 
    ... 
} 

करता Base के निर्माता Super निर्माता ओवरराइड? यदि ऐसा है, तो फ़ील्ड 1 को प्रारंभ करने की गारंटी नहीं दी जाती है, जिससे विरासत विधियां अप्रत्याशित रूप से व्यवहार करती हैं।

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

+0

इस काउंटर-उदाहरण के साथ समस्या यह है कि इसमें डिफ़ॉल्ट कन्स्ट्रक्टर शामिल नहीं हैं। आप सही हैं कि यह कोड समस्याग्रस्त है; यह संकलन भी नहीं करेगा। हालांकि, मेरा प्रश्न विशेष रूप से डिफ़ॉल्ट रचनाकारों के आसपास है। – arootbeer

+0

आपका उदाहरण काम करता है क्योंकि उप के पास कोई कन्स्ट्रक्टर नहीं है, और यदि रचनाकारों को केवल उन मामलों में विरासत में मिला तो यह एक भ्रमित विशेषता होगी। –

+0

मेरा उदाहरण केवल समस्याग्रस्त है क्योंकि 'उप' में कोई रचनाकार नहीं है। मैं आपसे सहमत हूं कि यह भ्रमित होगा, लेकिन यह सवाल यह है कि यह भ्रमित करने का प्रयास क्यों करना है कि यह भ्रमित क्यों होगा। – arootbeer

0

मैं इसे इस व्यवहार के तकनीकी कारण के रूप में डाल रहा हूं; मैं कई अन्य उत्तरों के साथ समझौता कर रहा हूं कि यह अर्थात् भ्रमित हो सकता है।

निम्न उदाहरण पर विचार करें:

public class A { } 

public abstract class Super { 
    protected Super() { 
     // perform time consuming, destructive, or 
     // otherwise one-time operations 
    } 

    public Super(A a) { 
     this(); 
     // perform A-related construction operations 
    } 
} 

public class Sub extends Super { } 

public class Consumer { 
    public Consumer() { 
     Sub sub = new Sub(new A()); 
    } 
} 

जब Sub का निर्माण किया है, इस मामले में Sub पर डिफ़ॉल्ट निर्माता कहा जाता है, जो होगा Super पर डिफ़ॉल्ट निर्माता के लिए श्रृंखला (क्योंकि कि जादू भाषा है परिभाषित करता है)। फिर, Super(A) पर कॉल तर्क को आमंत्रित करेगा जिसे निर्माण पर एक बार चलाने के लिए डिज़ाइन किया गया है। यह स्पष्ट रूप से नहीं है कि डेवलपर क्या चाहता है।

this() के बिना भी Super(A) कन्स्ट्रक्टर में कॉल करें, डेवलपर का इरादा निर्धारित नहीं किया जा सकता है; कुछ कारणों से रचनाकार पारस्परिक रूप से अनन्य हो सकते हैं।

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