क्या जावा सी परिभाषाओं और कार्यान्वयन के बीच अलगाव को बढ़ावा देता है, जैसा कि C ++ है?


10

मेरे पास एक होमवर्क असाइनमेंट है और मुझे यह मूल्यांकन करने की आवश्यकता है कि जीआरएएसपी "संरक्षित विविधता" के अनुसार कौन सा दृष्टिकोण बेहतर है। मुझे C ++ में हेडर और कोड फ़ाइलों के पृथक्करण के बारे में स्टैक ओवरफ्लो पर एक प्रश्न मिला ।

हालाँकि, मैं यह जानना चाहता हूं कि जावा वर्ग परिभाषाओं और वर्ग कार्यान्वयन के बीच अलगाव को बढ़ावा देने में C ++ का पालन क्यों नहीं करता है। क्या सी ++ विधि से अधिक जावा विधि के साथ कोई लाभ हैं?


यदि आप पूछना चाहते हैं "जावा हेडर फ़ाइलों का उपयोग क्यों नहीं करता है", तो बस पूछें और "जो बेहतर है" सामान के साथ दूर करें - जैसा कि आपने देखा है, हमें उससे एलर्जी है;) इसके अलावा, खोज इससे पहले कि मैं निश्चित रूप से यह (या कम से कम बारीकी से संबंधित प्रश्न) लाया हूँ।

ओह, लिंक काम नहीं किया। मैं सुधार करूँगा, जो मैं मूल रूप से जानना चाहता था, उन दोनों के बीच का अंतर है और जो कोड का पुन: उपयोग या अधिकता के लिए अधिक आसान हो जाता है।
एटिने नोएल

1
सी (और विस्तार द्वारा C ++) के पास वास्तव में कोई विकल्प नहीं था लेकिन हेडर फ़ाइलों को कार्यान्वयन फ़ाइलों से अलग करने के लिए, सी के निर्माण के समय सीमित वन-पास कंपाइलर तकनीक के कारण।
Channel72

2
जावा में इंटरफेस हो सकते हैं जो वर्ग परिभाषा और वर्ग कार्यान्वयन को अलग कर सकते हैं, यदि प्रश्न में वर्ग इंटरफ़ेस को लागू करता है। हालांकि C ++ के समान नहीं है।
FrustratedWithFormsDesigner

1
जब तक आप PIMPL मुहावरे का उपयोग नहीं करते हैं, तब तक, C ++ हैडर फाइलें मेरे द्वारा पसंद किए जाने से अधिक कार्यान्वयन को उजागर करती हैं। सभी डेटा सदस्यों को सूचीबद्ध करना आवश्यक है, भले ही private, इसलिए कार्यान्वयन को आकार पता होगा, और privateसदस्य कार्य भी।
डेविड थार्नले

जवाबों:


13

निम्नलिखित कार्यक्रम में कोड की कितनी लाइनें हैं?

#include <iostream>

int main()
{
   std::cout << "Hello, world!\n";
   return 0;
}

आपने शायद 7 (या 6 का उत्तर दिया है यदि आपने रिक्त पंक्ति की गणना नहीं की है, या 4 यदि आपने ब्रेसिज़ की गिनती नहीं की है)।

हालाँकि आपका कंपाइलर कुछ अलग देखता है:

~$ cpp hello.cpp | wc
  18736   40822  437015

हाँ, यह 18.7 KLOC सिर्फ एक "हैलो, दुनिया!" कार्यक्रम। C ++ कंपाइलर को वह सब पार्स करना होगा। यह एक प्रमुख कारण है कि अन्य भाषाओं की तुलना में C ++ संकलन में इतना समय लगता है , और आधुनिक भाषाओं ने हेडर फ़ाइलों को क्यों बढ़ाया।

एक बेहतर सवाल होगा

C ++ में हेडर फाइलें क्यों होती हैं ?

C ++ को C के एक सुपरसेट के रूप में डिजाइन किया गया था, इसलिए इसे पीछे की संगतता के लिए हेडर फ़ाइलों को रखना पड़ता था।

ठीक है, तो सी में हेडर फाइलें क्यों हैं?

अपने आदिम अलग संकलन मॉडल के कारण। C कंपाइलर्स द्वारा बनाई गई ऑब्जेक्ट फाइल्स में किसी भी प्रकार की जानकारी शामिल नहीं है, इसलिए इस प्रकार की त्रुटियों को रोकने के लिए आपको अपने सोर्स कोड में इस जानकारी को शामिल करना होगा।

~$ cat sqrtdemo.c 
int main(void)
{
    /* implicit declaration int sqrt(int) */
    double sqrt2 = sqrt(2);
    printf("%f\n", sqrt2);
    return 0;
}

~$ gcc -Wall -ansi -lm -Dsqrt= sqrtdemo.c
sqrtdemo.c: In function main’:
sqrtdemo.c:5:5: warning: implicit declaration of function printf [-Wimplicit-function-declaration]
sqrtdemo.c:5:5: warning: incompatible implicit declaration of built-in function printf [enabled by default]
~$ ./a.out 
2.000000

उचित प्रकार की घोषणाओं को जोड़ना बग को ठीक करता है:

~$ cat sqrtdemo.c 
#undef printf
#undef sqrt

int printf(const char*, ...);
double sqrt(double);

int main(void)
{
    double sqrt2 = sqrt(2);
    printf("%f\n", sqrt2);
    return 0;
}

~$ gcc -Wall -ansi -lm sqrtdemo.c
~$ ./a.out 
1.414214

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

हेडर फ़ाइलों से बचने के लिए आधुनिक भाषाएं कैसे सक्षम हैं?

किसी भिन्न ऑब्जेक्ट फ़ाइल स्वरूप का उपयोग करके जिसमें टाइप जानकारी शामिल है। उदाहरण के लिए, जावा * .class फ़ाइल प्रारूप में "डिस्क्रिप्टर" शामिल हैं जो फ़ील्ड और विधि पैरामीटर के प्रकार निर्दिष्ट करते हैं।

यह कोई नया आविष्कार नहीं था। इससे पहले (1987), जब बोरलैंड ने टर्बो पास्कल 4.0 के लिए अलग से संकलित "इकाइयां" जोड़ीं, तो उसने हेडर फ़ाइलों की आवश्यकता को हटाने के लिए *.TPUटर्बो सी के बजाय एक नए प्रारूप का उपयोग करना चुना *.OBJ


हालाँकि दिलचस्प है, मुझे पूरा यकीन है कि आप टर्बो पास्कल को आउटपुट OBJफाइल के बजाय TPUs ...
a CVn

7

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

मान लीजिए कि आप एक ऐसी विधि लिखना चाहते हैं जो मानचित्र में सभी कुंजी / मानों को धीमा कर दे।

public static <K,V> void printMap(Map<K,V> map) {
    for(Entry<K,V> entry: map.entrySet())
        System.out.println(entry);
}

यह विधि एंट्रेससैट () को एक सार इंटरफेस पर कह सकती है जो इसे लागू करने वाले वर्ग से हटा दिया जाता है। आप इस विधि से कॉल कर सकते हैं।

printMap(new TreeMap());
printMap(new LinkedHashMap());
printMap(new ConcurrentHashMap());
printMap(new ConcurrentSkipListMap());

1
वहाँ पीटर के लिए आपका स्वागत है - मुझे लगा कि मैंने नाम :-) को पहचान लिया है। मैं जोड़ूंगा कि कुछ लोग तर्क देंगे कि जावा में एब्सट्रैक्ट बेस क्लास भी एक अनुबंध को परिभाषित करते हैं - लेकिन यह शायद एक अलग धागे के लिए एक तर्क है।
Martijn Verburg

नमस्ते @MartijnVerburg, इसके अलावा अच्छा है। मुझे लगता है कि अमूर्त वर्ग कार्यान्वयन और ठोस वर्गों के बिना इंटरफेस के बीच अंतर को धुंधला करते हैं। विस्तार के तरीकों से आगे भी अंतर धुंधला जाएगा। मैं एक इंटरफ़ेस का उपयोग करना पसंद करता हूं यदि मैं सरल हो सकता हूं।
पीटर लॉरी

हाँ जावा एक सार्वजनिक अनुबंध को परिभाषित करने के कई तरीके होने के स्काला पथ के नीचे उतरना शुरू करने जा रहा है - मुझे यकीन नहीं है कि यह एक अच्छी बात है या अभी तक नहीं है :-)
मार्टिज्न वर्बर्ग

-1 C ++ में यह संभव है, एक सरल के साथ #define interface class
Sjoerd

@Sjoerd मुझे नहीं पता था कि C ++ विधियों को अब virtualबहुरूपता प्राप्त करने के लिए कीवर्ड का उपयोग करने की आवश्यकता नहीं है और इसका कोई निष्पादन जुर्माना नहीं है यदि आप केवल एक या दो ठोस प्रकारों का उपयोग करते हैं, जैसे कि वे जावा में हैं। क्या आप मुझे किसी भी दस्तावेज पर यह इंगित कर सकते हैं कि यह C ++ में कैसे काम करता है?
पीटर लॉरी

5

हेडर्स मौजूद हैं, एक ऐतिहासिक दुर्घटना के रूप में, काफी स्पष्ट रूप से। यह एक अविश्वसनीय रूप से खराब प्रणाली है, किसी भी अन्य भाषा में इतना भयानक कुछ भी नहीं है, और जिस किसी को भी उनसे निपटने की ज़रूरत नहीं है, उसे आनन्दित होना चाहिए।


3

अलग संकलन को सक्षम करने के लिए हेडर हैं। # हेडर को छोड़कर, संकलक को C ++ कोड की बाइनरी संरचना के बारे में कुछ भी जानने की आवश्यकता नहीं है, और वह नौकरी को एक अलग लिंकर से छोड़ सकता है। जावा अपने संकलक के साथ एक अलग लिंकर का उपयोग नहीं करता है, और चूंकि .class फ़ाइलों को कड़ाई से परिभाषित किया गया है, संकलक उन्हें अपने सभी सदस्यों को अपने सभी प्रकारों के साथ निर्धारित करने में सक्षम है, बिना किसी संकलन इकाई में उन्हें फिर से घोषित करने की आवश्यकता है।

आप सभी कार्यान्वयन को C ++ हैडर में शामिल कर सकते हैं, लेकिन यह कंपाइलर को हर बार इसे फिर से जोड़ने के लिए प्रेरित करता है, जिससे लिंक करने वाले को छांटने और डुप्लिकेट प्रतियों को छोड़ने के लिए मजबूर होना पड़ता है।


0

जावा वर्ग परिभाषा और कार्यान्वयन के अलगाव को बढ़ावा देता है, यह सिर्फ यह निर्भर करता है कि आप कहाँ से देख रहे हैं।

जब आप एक जावा वर्ग के लेखक होते हैं, तो आपको कक्षा की परिभाषा के साथ-साथ एक फ़ाइल में इसके कार्यान्वयन को भी देखने को मिलता है। यह विकास प्रक्रिया को सरल बनाता है क्योंकि आपने कक्षा को बनाए रखने के लिए केवल एक स्थान पर जाने के लिए गोर किया है, आपको दो फ़ाइलों (.h .cpp और C ++ में होगा) के बीच स्विच करने की आवश्यकता नहीं है। हालाँकि, जब आप वर्ग के उपभोक्ता होते हैं तो आप केवल एक .class फ़ाइल के माध्यम से परिभाषा के साथ सौदा करते हैं, जो या तो एक .jar या एक स्टैंडअलोन .clack में पैक की जाती है।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.