2009-01-11 32 views
16

new operator क्यों आधुनिक भाषाओं जैसे सी # और जावा में मौजूद है? क्या यह पूरी तरह से एक स्वयं दस्तावेज़ कोड सुविधा है, या यह किसी भी वास्तविक उद्देश्य की सेवा करता है?सी # और जावा "नए" ऑपरेटर से परेशान क्यों हैं?

उदाहरण के लिए निम्न उदाहरण:

Class1 obj = new Class1(); 

Class1 foo() 
{ 
    return new Class1(); 
} 

इसे लिखने के अधिक Pythonesque तरीके के रूप में पढ़ने के लिए के रूप में आसान है:

Class1 obj = Class1(); 

Class1 foo() 
{ 
    return Class1(); 
} 

संपादित करें: Cowan स्पष्टीकरण के साथ सिर पर कील मारा प्रश्न का: उन्होंने इस वाक्यविन्यास का चयन क्यों किया?

उत्तर

23
  1. यह एक स्वयं कुछ दस्तावेज़ीकृत सुविधा है के साथ काम कर रहे हैं।
  2. यह यह संभव कुछ अन्य वर्ग
+0

मुझे वास्तव में आपका दूसरा बिंदु पसंद है। – dalle

+1

दूसरे बिंदु पर: आप वैसे भी ऐसा कर सकते हैं, लेकिन इसे इसके साथ अर्हता प्राप्त करनी थी। क्लास 1()। वही बात तब होती है जब प्रकार और सदस्य नाम टकराते हैं। –

+0

यह सच है, लेकिन आपके पास पठनीयता समस्याएं हो सकती हैं। – Paco

1

नया ऑपरेटर ऑब्जेक्ट (ओं) के लिए स्मृति आवंटित करता है, जिसका उद्देश्य है; आप भी यह कहना ही आत्म दस्तावेजों जो उदाहरण (रों) (अर्थात एक नया एक) आप

+0

सी # में structs के लिए नया कॉलिंग हालांकि स्मृति आवंटित नहीं करता है। – dalle

+0

यह केवल ढेर पर है, ढेर –

+0

की तुलना में, वास्तव में, फ़ंक्शन दर्ज होने पर पहले ही आवंटित किया जाता है। – dalle

9
Class1 obj = Class1(); 

सी # और जावा में, आप की जरूरत है 'नई' क्योंकि इसके बिना कीवर्ड में एक विधि "Class1" नाम के लिए बनाने के लिए एक तरह से है, यह व्यवहार करता है "Class1() "एक विधि के लिए कॉल के रूप में जिसका नाम" कक्षा 1 "है।

+0

सच है, लेकिन अगर ऐसा नहीं होता तो क्या होगा? 'नया' ऑपरेटर पहले स्थान पर क्यों मौजूद है? – dalle

+1

लेकिन वह * मामला है। आप पूछ रहे हैं, "क्या होगा यदि ऐसा कोई मामला नहीं था कि कोई इंजन कार चलाए? एक 'इंजन' पहले स्थान पर क्यों मौजूद है? " – Michael

+0

क्या होगा यदि कोई घोड़ा कार चला रहा है और इंजन सिर्फ रेडियो और एयर कंडीशनिंग को नियंत्रित करता है? या क्या होगा यदि कोई अन्य प्रकार की कार इंजन के बिना आगे बढ़ सकती है? – Paco

-2

क्या आपने स्थिर तरीकों का उपयोग करने पर विचार किया है?

class Class1 
{ 
    public static Class1 Instance() { return new Class1(); } 
} 

Class1 obj = Class1.Instance(); 

Class1 foo() 
{ 
    return Class1.Instance(); 
} 
+0

प्रत्येक स्थिति के लिए स्थिर विधियां लागू नहीं हैं – sarsnake

5

सी # में नए ऑपरेटर आईएल अनुदेश जो वास्तव में नई वस्तु के चर के लिए अंतरिक्ष आवंटित करता है और फिर निर्माता (IL में .ctor कहा जाता है) को निष्पादित करता newobj कहा जाता है के लिए सीधे मैप करता है। कन्स्ट्रक्टर को निष्पादित करते समय - सी ++ की तरह - आरंभिक ऑब्जेक्ट का संदर्भ अदृश्य पहले पैरामीटर (thiscall) के रूप में पारित किया जाता है।

इस तरह की सम्मेलन रनटाइम को लोड करने की अनुमति देता है और जेआईटी को केवल एक बार एक विशिष्ट वर्ग के लिए स्मृति में कोड और कक्षा के हर उदाहरण के लिए इसका पुन: उपयोग करने की अनुमति देता है।

जावा के मध्यवर्ती भाषा में एक समान ओपोड हो सकता है, सोचा कि मैं कहने के लिए पर्याप्त परिचित नहीं हूं।

9

उपयोगिता दस्तावेज़ीकरण की है - पाइथन की तुलना में विधि आमंत्रण से वस्तु निर्माण को अलग करना आसान है।

कारण ऐतिहासिक है, और सीधे सी ++ वाक्यविन्यास से आता है। सी ++ में, "कक्षा 1()" एक अभिव्यक्ति है जो क्लास 1 उदाहरण स्टैक पर बना रही है। उदाहरण के लिए: वेक्टर ए = वेक्टर(); इस मामले में, एक वेक्टर बनाया जाता है और वेक्टर ए में प्रतिलिपि बनाई जाती है (एक ऑप्टिमाइज़र कुछ मामलों में अनावश्यक प्रति को हटा सकता है)।

इसके बजाय, "नई Class1()" एक Class1 उदाहरण ढेर पर बनाता है, जावा और सी # में की तरह है, और यह करने के लिए एक सूचक देता है, एक अलग पहुँच वाक्य रचना के साथ, के विपरीत जावा और सी ++। असल में, नए का अर्थ किसी विशेष उद्देश्य आवंटक का उपयोग करने के लिए फिर से परिभाषित किया जा सकता है, जिसे अभी भी किसी प्रकार के ढेर का संदर्भ देना चाहिए, ताकि प्राप्त वस्तु संदर्भ द्वारा वापस की जा सके।

इसके अलावा, जावा/सी #/सी ++, कक्षा 1() में स्वयं किसी भी विधि/कार्य को संदर्भित कर सकता है, और यह भ्रमित होगा। जावा कोडिंग कन्वेंशन वास्तव में इससे बच जाएगा, क्योंकि उन्हें कक्षा के नामों को ऊपरी केस लेटर और विधि नामों से शुरू करने की आवश्यकता होती है, जो कम मामले में से शुरू होते हैं, और शायद यही कारण है कि पाइथन इस मामले में भ्रम से बचाता है। एक पाठक उम्मीद करता है कि "कक्षा 1()" ऑब्जेक्ट बनाने के लिए, "कक्षा 1()" एक फ़ंक्शन आमंत्रण होने के लिए, और "x.class1()" एक विधि आमंत्रण (जहां 'x' 'स्वयं' हो सकता है)।

अंत में, चूंकि पाइथन में उन्होंने कक्षाएं ऑब्जेक्ट्स बनाने और विशेष रूप से कॉल करने योग्य वस्तुओं को चुना है, बिना 'नए' के ​​वाक्यविन्यास की अनुमति होगी, और यह एक और वाक्यविन्यास होने की अनुमति देने के लिए असंगत होगा।

+2

यह सिर्फ इतना नहीं है; पाइथन में कार्यों और रचनाकारों के बीच एक अर्थपूर्ण अंतर नहीं, कम से कम कक्षा के बाहर से नहीं। जैसे ही आप 'def inc (ए) करेंगे: एक + 1 लौटें; नक्शा (inc, somelist) 'inc 'सोमालिस्ट' में सभी वस्तुओं का पुनर्मूल्यांकन करें, आप सभी वस्तुओं को 'somelist'' int में परिवर्तित करने के लिए 'मानचित्र (int, somelist)' कर सकते हैं। – Imagist

2

सी ++ प्रोग्रामर को ढेर या ढेर पर ऑब्जेक्ट आवंटित करने का विकल्प प्रदान करता है।

स्टैक-आधारित आवंटन more efficient है: आवंटन सस्ता है, डीलोकेशन लागत वास्तव में शून्य है, और भाषा ऑब्जेक्ट लाइफसाइक्सेस को कम करने में सहायता प्रदान करती है, जिससे ऑब्जेक्ट को मुक्त करने के जोखिम को कम किया जाता है।
दूसरी तरफ, सी ++ में, आपको स्टैक-आधारित ऑब्जेक्ट्स के संदर्भों को प्रकाशित या साझा करते समय बहुत सावधान रहना होगा क्योंकि स्टैक-फ्रेम ऑब्जेक्ट स्वचालित रूप से मुक्त हो जाते हैं जब स्टैक फ्रेम अवांछित होता है, जिससे लटकने वाले पॉइंटर्स होते हैं।

new ऑपरेटर के साथ, सभी ऑब्जेक्ट्स जावा या सी # में ढेर पर आवंटित किए जाते हैं।

कक्षा 1 ओबीजे = कक्षा 1();

वास्तव में, संकलक एक विधि Class1() बुलाया खोजने की कोशिश करेंगे।

उदा।

public class MyClass 
{ 
    //Oops, this has a return type, so its a method not a constructor! 
    //Because no constructor is defined, Java will add a default one. 
    //init() will not get called if you do new MyClass(); 
    public void MyClass() 
    { 
    init(); 
    } 
    public void init() 
    { 
    ... 
    } 
} 

नोट:: निम्नलिखित एक आम जावा बग है "सभी वस्तुओं ढेर पर आवंटित किए जाते हैं" मतलब यह नहीं है ढेर आवंटन कभी कभी हुड के नीचे किया जाता है।

उदाहरण के लिए, जावा में, escape analysis जैसे हॉटस्पॉट अनुकूलन स्टैक आवंटन का उपयोग करता है।

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

इस तरह के अनुकूलन हालांकि AFAIK ऊपर टिप्पणियों वे जल्दी ड्राफ्ट में जावा 7 के लिए नए कीवर्ड दूर करने के लिए योजना बना रहे थे के अलावा considereddecisive ...

0

हमेशा नहीं है। लेकिन बाद में उन्होंने इसे रद्द कर दिया।

2

जावा ने इसे चुना क्योंकि कारण सिंटैक्स सी ++ डेवलपर्स से परिचित था। सी # ने इसका कारण चुना क्योंकि यह जावा डेवलपर्स से परिचित था।

कारण new ऑपरेटर का उपयोग सी ++ में किया जाता है शायद मैन्युअल मेमोरी प्रबंधन के साथ स्मृति आवंटित होने पर इसे स्पष्ट करना बहुत महत्वपूर्ण है। जबकि पायथनस सिंटैक्स काम कर सकता है, यह कम स्पष्ट है कि स्मृति आवंटित की जाती है।

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