C ++ के विपरीत, Java में, हम कक्षा में केवल कक्षा के बाहर परिभाषाएँ और परिभाषाएँ नहीं दे सकते। ऐसा क्यों है?
क्या यह ज़ोर देना है कि जावा में एक एकल फ़ाइल में केवल एक वर्ग होना चाहिए और कुछ नहीं?
C ++ के विपरीत, Java में, हम कक्षा में केवल कक्षा के बाहर परिभाषाएँ और परिभाषाएँ नहीं दे सकते। ऐसा क्यों है?
क्या यह ज़ोर देना है कि जावा में एक एकल फ़ाइल में केवल एक वर्ग होना चाहिए और कुछ नहीं?
जवाबों:
C ++ और Java के बीच का अंतर यह है कि भाषाओं को उनके लिंकेज की सबसे छोटी इकाई मानते हैं।
क्योंकि C को असेंबली के साथ सह-अस्तित्व के लिए डिज़ाइन किया गया था, इसलिए यह इकाई एक पते द्वारा कहे जाने वाले सबरूटीन है। (यह अन्य भाषाओं के लिए सही है जो देशी ऑब्जेक्ट फ़ाइलों के लिए संकलित करता है, जैसे कि FORTRAN।) दूसरे शब्दों में, एक फ़ंक्शन वाली ऑब्जेक्ट फ़ाइल में foo()
एक प्रतीक _foo
होगा जिसका नाम एक ऐसा प्रतीक होगा जिसे कुछ भी नहीं बल्कि एक पते के रूप में हल किया जाएगा।0xdeadbeef
लिंकिंग के दौरान। बस इतना ही है। यदि फ़ंक्शन तर्कों को लेना है, तो यह सुनिश्चित करने के लिए कॉल करने वाले पर निर्भर है कि फ़ंक्शन को उसके पते पर कॉल करने से पहले क्या अपेक्षा है। आम तौर पर, यह स्टैक पर चीजों को जमा करके किया जाता है, और कंपाइलर ग्रंट काम का ख्याल रखता है और यह सुनिश्चित करता है कि प्रोटोटाइप मेल खाते हैं। ऑब्जेक्ट फ़ाइलों के बीच इसकी कोई जाँच नहीं है; यदि आप कॉल लिंकेज को भूल जाते हैं, तो कॉल योजना के अनुसार नहीं जा रही है और आपको इसके बारे में चेतावनी नहीं मिलने वाली है। खतरे के बावजूद, यह कई भाषाओं (असेंबली सहित) से संकलित ऑब्जेक्ट फ़ाइलों के लिए बहुत सारे उपद्रव के बिना एक कार्यशील कार्यक्रम में एक साथ जुड़ा होना संभव बनाता है।
सी ++, अपने सभी अतिरिक्त काल्पनिकता के बावजूद, उसी तरह से काम करता है। कंपाइलर शूहॉर्न नामस्थान, वर्ग और विधियाँ / सदस्य / आदि। इस सम्मेलन में वर्गों की सामग्रियों को एकल नामों में समतल करके, जो एक तरह से मंगवाए गए हैं, जो उन्हें अद्वितीय बनाते हैं। उदाहरण के लिए, की तरह एक विधि Foo::bar(int baz)
में घायल हो सकता है _ZN4Foo4barEi
जब एक वस्तु फ़ाइल और की तरह एक पते में डाल दिया 0xBADCAFE
रनटाइम पर। यह पूरी तरह से कंपाइलर पर निर्भर करता है, इसलिए यदि आप दो वस्तुओं को जोड़ने की कोशिश करते हैं, जिनमें अलग-अलग मैनबलिंग स्कीम हैं, तो आप भाग्य से बाहर होंगे। बदसूरत के रूप में यह है, इसका मतलब है कि आप extern "C"
manबल को निष्क्रिय करने के लिए एक ब्लॉक का उपयोग कर सकते हैं , जिससे C ++ कोड को अन्य भाषाओं में आसानी से उपलब्ध कराया जा सकता है। C ++ को C से मुक्त-फ़्लोटिंग फ़ंक्शंस की धारणा विरासत में मिली, मोटे तौर पर क्योंकि देशी ऑब्जेक्ट प्रारूप इसकी अनुमति देता है।
जावा एक अलग जानवर है जो अपने ऑब्जेक्ट फ़ाइल प्रारूप, फ़ाइल के साथ एक अछूता दुनिया में रहता है .class
। क्लास फ़ाइलों में उनकी सामग्री के बारे में जानकारी होती है जो पर्यावरण को रनटाइम पर कक्षाओं के साथ चीजों को करने की अनुमति देती है जो देशी लिंकेज तंत्र के बारे में सपने में भी नहीं सोच सकता है। उस जानकारी को कहीं से शुरू करना है, और यह शुरुआती बिंदु हैclass
। उपलब्ध जानकारी संकलित कोड को स्रोत कोड में विवरण सहित अलग-अलग फ़ाइलों की आवश्यकता के बिना स्वयं का वर्णन करने की अनुमति देती है, जैसा कि आपके पास C, C ++ या अन्य भाषाओं में होगा। जो आपको रनटाइम के दौरान भी मूल लिंकेज की कमी का उपयोग करते हुए सभी प्रकार की सुरक्षा लाभ वाली भाषाएं देता है, और वह वह है जो आपको प्रतिबिंब का उपयोग करके एक फ़ाइल से बाहर एक मनमानी वर्ग को मछली देने में सक्षम बनाता है और अगर कुछ मेल नहीं खाता है तो गारंटी विफलता के साथ इसका उपयोग करें ।
यदि आपने पहले ही इसका पता नहीं लगा लिया है, तो यह सभी सुरक्षा एक ट्रेडऑफ़ के साथ आती है: कुछ भी जो आप एक जावा प्रोग्राम से जोड़ते हैं, वह है जावा। (द्वारा "लिंक," मेरा मतलब है कि किसी भी एक वर्ग फ़ाइल में किसी भी चीज का मतलब दूसरे में कुछ होता है।) आप जेएनआई का उपयोग करके मूल कोड में (मूल अर्थ में) लिंक कर सकते हैं , लेकिन एक अंतर्निहित अनुबंध है जो कहता है कि यदि आप मूल पक्ष को तोड़ते हैं , आप दोनों टुकड़ों के मालिक हैं।
जावा बड़ा था और विशेष रूप से उपलब्ध हार्डवेयर पर तेज़ नहीं था जब इसे पहली बार पेश किया गया था, तो आद्या जैसा बहुत कुछ पहले के दशक में हुआ था। केवल जिम गोस्लिंग यह सुनिश्चित करने के लिए कह सकते हैं कि क्लास जावा की सबसे छोटी इकाई लिंकेज बनाने में उनकी प्रेरणाएँ क्या थीं, लेकिन मुझे यह अनुमान लगाना होगा कि अतिरिक्त फ्लोटर्स जो रनटाइम में जोड़े जाते हैं, वह एक सौदा-हत्यारा हो सकता है।
मेरा मानना है कि उत्तर विकिपीडिया के अनुसार, जावा को सरल और वस्तु उन्मुख बनाया गया था। फ़ंक्शंस उन कक्षाओं पर काम करने के लिए होती हैं जिन्हें वे परिभाषित करते हैं। सोच की उस रेखा के साथ, क्लास के बाहर कार्य करने का कोई मतलब नहीं है। मैं इस निष्कर्ष पर छलांग लगाने जा रहा हूं कि जावा इसे अनुमति नहीं देता क्योंकि यह शुद्ध ओओपी के साथ फिट नहीं था।
मेरे लिए एक त्वरित Google खोज जावा भाषा डिजाइन प्रेरणाओं पर ज्यादा उपज नहीं देती थी।
असली सवाल यह है कि सी ++ तरीके से चीजों को जारी रखने की योग्यता क्या होगी और हेडर फाइल का मूल उद्देश्य क्या था? संक्षिप्त उत्तर यह है कि हेडर फ़ाइल शैली को बड़ी परियोजनाओं पर त्वरित संकलन समय के लिए अनुमति दी जाती है जिसमें कई वर्ग संभावित रूप से एक ही प्रकार का संदर्भ दे सकते हैं। यह संकलक की प्रकृति के कारण जावा और .NET में आवश्यक नहीं है।
इस उत्तर को यहां देखें: क्या हेडर फाइलें वास्तव में अच्छी हैं?
interface
और class
:) हेडर की कोई आवश्यकता नहीं है!
एक जावा फ़ाइल एक वर्ग का प्रतिनिधित्व करती है। यदि आपके पास कक्षा से बाहर की प्रक्रिया है, तो क्या गुंजाइश होगी? क्या यह वैश्विक होगा? या यह उस वर्ग का होगा जो जावा फ़ाइल का प्रतिनिधित्व करता है?
संभवतया, आप इसे किसी कारण के लिए किसी अन्य फ़ाइल के बजाय उस जावा फ़ाइल में डालते हैं - क्योंकि यह किसी अन्य वर्ग की तुलना में उस वर्ग के साथ जाती है। यदि किसी वर्ग के बाहर की प्रक्रिया वास्तव में उस वर्ग के साथ जुड़ी थी, तो उसे उस वर्ग के अंदर जाने के लिए मजबूर क्यों नहीं किया जाता है जहां वह है? जावा इसे कक्षा के अंदर एक स्थिर विधि के रूप में संभालता है।
यदि एक बाहरी श्रेणी की प्रक्रिया की अनुमति दी गई थी, तो यह संभवतः उस वर्ग के लिए कोई विशेष पहुंच नहीं होगी जिसकी फ़ाइल में इसे घोषित किया गया था, इस प्रकार इसे एक उपयोगिता फ़ंक्शन तक सीमित किया गया है जो किसी भी डेटा को नहीं बदलता है।
इस जावा सीमा के लिए केवल संभव डाउन-साइड यह है कि यदि आपके पास वास्तव में वैश्विक प्रक्रियाएं हैं जो किसी भी वर्ग से जुड़ी नहीं हैं, तो आप उन्हें रखने के लिए एक MyGlobals वर्ग बनाते हैं, और अपनी सभी अन्य फ़ाइलों में उस वर्ग को आयात करते हैं जो उन प्रक्रियाओं का उपयोग करते हैं ।
वास्तव में, जावा आयात तंत्र को कार्य करने के लिए इस प्रतिबंध की आवश्यकता होती है। एपीआई के सभी उपलब्ध होने के साथ, जावा कंपाइलर को यह जानने की जरूरत है कि क्या संकलन करना है और किसके खिलाफ संकलन करना है, इस प्रकार फ़ाइल के शीर्ष पर स्पष्ट आयात विवरण। अपने ग्लोबल्स को एक कृत्रिम वर्ग में समूहित किए बिना, आप जावा कंपाइलर को अपने ग्लोबल्स को संकलित करने के लिए कैसे कहेंगे और कोई भी नहीं ग्लोबल्स को आपके क्लासपाथ पर नहीं? नाम-स्थान टकराव के बारे में क्या है जहाँ आपके पास एक doStuff () और किसी और के पास doStuff () है? यह काम नहीं करेगा। आपको MyClass.doStuff () और YourClass.doStuff () निर्दिष्ट करने के लिए इन समस्याओं को हल करने के लिए मजबूर करता है। अपनी प्रक्रियाओं को बाहर करने के बजाय MyClass के अंदर जाने के लिए मजबूर करना केवल इस प्रतिबंध को स्पष्ट करता है और आपके कोड पर अतिरिक्त प्रतिबंध नहीं लगाता है।
जावा को कई चीजें गलत लगीं - क्रमबद्धता इतने कम मौसा हैं कि उपयोगी होना लगभग मुश्किल है (सोचिए SerialVersionUID)। इसका उपयोग एकल और अन्य सामान्य डिज़ाइन पैटर्न को तोड़ने के लिए भी किया जा सकता है। ऑब्जेक्ट पर क्लोन () विधि को डीप क्लोन () और उथले क्लोन () में विभाजित किया जाना चाहिए और टाइप-सुरक्षित होना चाहिए। सभी एपीआई वर्गों को डिफ़ॉल्ट रूप से अपरिवर्तनीय बनाया जा सकता है (जिस तरह वे स्काला में हैं)। लेकिन सभी प्रक्रियाओं को एक वर्ग से संबंधित होने पर प्रतिबंध एक अच्छा है। यह मुख्य रूप से किसी भी प्रकार के प्रतिबंधों को लागू किए बिना भाषा और आपके कोड को सरल और स्पष्ट करने का कार्य करता है।
मुझे लगता है कि जवाब देने वाले अधिकांश लोगों और उनके मतदाताओं ने इस प्रश्न को गलत समझा है। यह दर्शाता है कि वे C ++ नहीं जानते हैं।
"परिभाषा" और "घोषणा" C ++ में बहुत विशिष्ट अर्थ वाले शब्द हैं।
ओपी का मतलब जावा के काम करने के तरीके को बदलना नहीं है। यह शुद्ध रूप से वाक्य रचना के बारे में एक प्रश्न है। मुझे लगता है कि यह एक वैध प्रश्न है।
C ++ में मेंबर फंक्शन को परिभाषित करने के दो तरीके हैं ।
पहला तरीका जावा तरीका है। बस सभी कोड ब्रेसिज़ के अंदर रखें:
class Box {
public:
// definition of member function
void change(int newInt) {
this._m = newInt;
}
private:
int _m
}
दूसरा तरीका:
class Box {
public:
// declaration of member function
void change(int newInt);
private:
int _m
}
// definition of member function
// this can be in the same file as the declaration
void Box::change(int newInt) {
this._m = newInt;
}
दोनों कार्यक्रम समान हैं। फ़ंक्शन change
अभी भी एक सदस्य फ़ंक्शन है: यह कक्षा के बाहर मौजूद नहीं है। इसके अलावा कक्षा की परिभाषा में जावा की तरह ही सभी सदस्य कार्यों और चर के नाम और प्रकार शामिल होने चाहिए।
जोनाथन हेंसन सही कहते हैं कि यह C ++ में हेडर के काम करने के तरीके की एक कला है: यह आपको हेडर फ़ाइल और कार्यान्वयन में घोषणाओं को एक अलग .cpp फ़ाइल में डालने की अनुमति देता है ताकि आपका प्रोग्राम ODR (वन डेफिनिशन रूल) का उल्लंघन न करे। लेकिन इसके बाहर गुण हैं: यह आपको एक नज़र में एक बड़े वर्ग के इंटरफ़ेस को देखने की अनुमति देता है।
जावा में आप अमूर्त कक्षाओं या इंटरफेस के साथ इस आशय का अनुमान लगा सकते हैं, लेकिन उन लोगों के पास कार्यान्वयन वर्ग के समान नाम नहीं हो सकता है, जो इसे बल्कि अनाड़ी बनाता है।
मुझे लगता है कि यह क्लास लोडिंग मैकेनिज्म की एक कलाकृति है। प्रत्येक कक्षा फ़ाइल एक लोड करने योग्य वस्तु के लिए एक कंटेनर है। वर्ग फ़ाइलों का "बाहर" कोई स्थान नहीं है।
C #, जो कि Java से बहुत मिलता-जुलता है, में आंशिक तरीकों के उपयोग के माध्यम से इस तरह की सुविधा है, सिवाय इसके कि आंशिक तरीके विशेष रूप से निजी हैं।
आंशिक तरीके: http://msdn.microsoft.com/en-us/library/6b0scde8.aspx
आंशिक कक्षाएं और तरीके: http://msdn.microsoft.com/en-us/library/wa80x488.aspx
मुझे कोई कारण नहीं दिखता है कि जावा ऐसा क्यों नहीं कर सकता है, लेकिन यह शायद नीचे आता है कि क्या इस सुविधा को भाषा में जोड़ने के लिए उपयोगकर्ता आधार से एक कथित आवश्यकता है।
C # के लिए अधिकांश कोड जनरेशन टूल आंशिक कक्षाएं उत्पन्न करते हैं ताकि डेवलपर आसानी से एक अलग फ़ाइल में वर्ग के लिए मैन्युअल रूप से लिखित कोड जोड़ सके, यदि वांछित है।
C ++ के लिए आवश्यक है कि कक्षा के पूरे पाठ को प्रत्येक संकलन इकाई के भाग के रूप में संकलित किया जाए जो किसी भी सदस्य का उपयोग करता है या कोई उदाहरण प्रस्तुत करता है। संकलित समय सारिणी रखने का एक ही तरीका है कि कक्षा का पाठ अपने आप में सम्मिलित हो - जहां तक संभव हो - केवल वे चीजें जो वास्तव में उसके उपभोक्ताओं के लिए आवश्यक हैं। तथ्य यह है कि सी ++ विधियों को अक्सर उन कक्षाओं के बाहर लिखा जाता है जिनमें उन्हें शामिल किया जाता है यह इस तथ्य से प्रेरित है कि वास्तव में एक बुरा हैक है जो कंपाइलर को प्रत्येक संकलन इकाई के लिए एक बार हर वर्ग विधि के पाठ को संसाधित करने की आवश्यकता होती है जहां कक्षा का उपयोग पूरी तरह से होता है। पागल निर्माण बार।
जावा में, संकलित वर्ग फ़ाइलों में अन्य चीजें, जानकारी होती हैं जो काफी हद तक C ++ .h फ़ाइल के बराबर होती हैं। संकलक प्रक्रिया .java फ़ाइल के बिना वर्ग के उपभोक्ता उस फ़ाइल से अपनी सभी जानकारी निकाल सकते हैं, जिसकी उन्हें आवश्यकता है। C ++ के विपरीत, जहां .h फ़ाइल में ऐसी जानकारी होती है, जो उसमें लागू की गई कक्षाओं के कार्यान्वयन और क्लाइंट दोनों के लिए उपलब्ध होती है, जावा में प्रवाह उल्टा हो जाता है: ग्राहकों द्वारा उपयोग की जाने वाली फ़ाइल एक स्रोत फ़ाइल नहीं है जो संकलन में उपयोग की गई है। क्लास कोड, लेकिन कंपाइलर द्वारा क्लास कोड फ़ाइल की जानकारी का उपयोग करके उत्पादित किया जाता है। चूँकि जानकारी क्लाइंट की आवश्यकता वाली फ़ाइल और कार्यान्वयन वाली फ़ाइल के बीच वर्ग कोड को विभाजित करने की कोई आवश्यकता नहीं है, जावा ऐसे विभाजन की अनुमति नहीं देता है।
मुझे लगता है कि इसका एक हिस्सा यह है कि जावा बहुत अधिक संरक्षणवादी भाषा है जो बड़ी टीमों पर उपयोग के साथ ही चिंता करती है। कक्षाओं को अधिलेखित या पुनर्परिभाषित नहीं किया जा सकता है। आपके पास पहुँच संशोधक के 4 स्तर हैं जो विशेष रूप से परिभाषित करते हैं कि कैसे तरीकों का उपयोग किया जा सकता है और उनका उपयोग नहीं किया जा सकता है। सब कुछ मजबूत / वैधानिक रूप से देवों को दूसरों या स्वयं के कारण होने वाले बेमेल हाइजिनक्स से बचाने के लिए टाइप किया जाता है। आपकी सबसे छोटी इकाइयों के रूप में कक्षाएं और फ़ंक्शन होने से यह बहुत आसान हो जाता है कि किसी ऐप को आर्किटेक्चर के बारे में कैसे जाना जाए।
जावास्क्रिप्ट की तुलना में जहां दोहरे उद्देश्य वाली संज्ञा / क्रिया प्रथम श्रेणी के कार्यों की बारिश होती है और एक खुली-खुली पिनाटा से कैंडी की तरह चारों ओर गुजरती है, कक्षा-समतुल्य फ़ंक्शन निर्माता इसके प्रोटोटाइप को नए गुणों को जोड़ने या पुराने उदाहरणों से बदलते हुए हो सकता है पहले से ही किसी भी समय बनाया गया है, बिल्कुल कुछ भी नहीं इसके निर्माण के अपने स्वयं के संस्करण के साथ किसी भी जगह से रोकता है, वहाँ 5 प्रकार की तरह है और वे अलग-अलग परिस्थितियों में ऑटो-कन्वर्ट और ऑटो-मूल्यांकन करते हैं और आप किसी भी चीज के पास लानत करने के लिए नए गुण संलग्न कर सकते हैं:
function nounAndVerb(){
}
nounAndVerb.newProperty = 'egads!';
अंततः यह niches और बाजारों के बारे में है। जावास्क्रिप्ट 100 के हाथों में उपयुक्त और विनाशकारी है (जिनमें से कई औसत दर्जे के होंगे) देवों के रूप में जावा एक बार देवों के छोटे समूहों के हाथों में था जो इसके साथ वेब यूआई लिखने की कोशिश कर रहे थे। जब आप 100 देवों के साथ काम कर रहे हैं तो आखिरी चीज जो आप चाहते हैं वह है कि एक व्यक्ति शापित प्रतिमान को फिर से स्थापित कर रहा है। जब आप यूआई या तेजी से विकास के साथ काम कर रहे हैं, तो एक अधिक महत्वपूर्ण चिंता का विषय है, आप चाहते हैं कि आखिरी बात यह है कि अपेक्षाकृत सरल चीजों को जल्दी से बस करने के लिए अवरुद्ध किया जाए क्योंकि यह बहुत ही मूर्खतापूर्ण तरीके से करना आसान होगा यदि आप सावधान नहीं हैं।
हालांकि दिन के अंत में, वे दोनों लोकप्रिय सामान्य उपयोग की भाषाएं हैं, इसलिए वहां एक दार्शनिक तर्क का एक सा है। जावा और सी # के साथ मेरा सबसे बड़ा व्यक्तिगत बीफ यह है कि मैंने कभी भी एक विरासत कोडबेस के साथ नहीं देखा या काम किया है, जहां अधिकांश देवों को लगता था कि बुनियादी ओओपी का मूल्य समझ में आया है। जब आप एक वर्ग में सब कुछ लपेटने वाले खेल में आते हैं, तो शायद यह मान लेना आसान हो जाता है कि आप 3-5 पंक्ति वर्गों की विशाल श्रृंखलाओं के रूप में प्रच्छन्न कार्य स्पगेटी के बजाय ओओपी कर रहे हैं।
उस ने कहा, जावास्क्रिप्ट से अधिक भयानक कुछ भी नहीं है जो किसी ने लिखा है जो केवल खतरनाक होना जानता है और इसे दिखाने से डरता नहीं है। और मुझे लगता है कि यह सामान्य विचार है। माना जाता है कि उस आदमी को जावा में लगभग समान नियमों से खेलना होगा। मेरा तर्क है कि कमीने को हमेशा एक रास्ता मिलेगा।