क्या विधि सिंटैक्टिक शुगर से अधिक कुछ भी लोड कर रही है? [बन्द है]


19

क्या विधि एक प्रकार का बहुरूपता है? मेरे लिए ऐसा लगता है कि बस एक ही नाम और विभिन्न मापदंडों के साथ तरीकों का अंतर है। तो stuff(Thing t)और stuff(Thing t, int n)जहाँ तक संकलक के रूप में पूरी तरह से अलग तरीके हैं और क्रम में चिंतित हैं।

यह कॉल करने वाले की ओर से भ्रम पैदा करता है, कि यह एक ही विधि है जो विभिन्न प्रकार की वस्तुओं पर अलग-अलग कार्य करती है - बहुरूपता। लेकिन यह केवल एक भ्रम है, क्योंकि वास्तव में stuff(Thing t)और stuff(Thing t, int n)पूरी तरह से अलग तरीके हैं।

क्या विधि सिंटैक्टिक शुगर से अधिक कुछ भी लोड कर रही है? क्या मैं कुछ भूल रहा हूँ?


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

एक वर्ग पर विचार करें:

class Reader {
    public String read(Book b){
        // .. translate the book to text
    }
    public String read(File b){
        // .. translate the file to text
    }
}

अब एक अन्य वर्ग पर विचार करें जो इस वर्ग का उपयोग करता है:

/* might not be the best example */
class FileProcessor {
    Reader reader = new Reader();
    public void process(File file){
        String text = reader.read(file);
        // .. do stuff with the text
    }
}

ठीक है। अब देखते हैं कि अगर हम नियमित तरीकों से ओवरलोडिंग के तरीके को बदल दें तो क्या बदलाव करने की जरूरत है:

readमें तरीकों Readerको बदलने के लिए readBook(Book)और readFile(file)। केवल उनके नाम बदलने की बात है।

FileProcessorपरिवर्तनों में कॉलिंग कोड : में reader.read(file)परिवर्तन होता है reader.readFile(file)

और बस।

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

अगर आपको कुछ है तो मैं आपकी आपत्तियाँ सुनना चाहूँगा, शायद मुझे कुछ याद आ रहा है।


48
अंत में, किसी भी प्रोग्रामिंग भाषा की सुविधा कच्चे कोडांतरक के लिए सिर्फ वाक्यविन्यास चीनी है।
फिलिप

31
@Philipp: क्षमा करें, लेकिन यह वास्तव में एक मूर्खतापूर्ण कथन है। प्रोग्रामिंग भाषाएं शब्दार्थ से उनकी उपयोगिता प्राप्त करती हैं, वाक्य रचना नहीं। एक प्रकार की प्रणाली जैसी विशेषताएं आपको वास्तविक गारंटी देती हैं, भले ही उन्हें वास्तव में आपको अधिक लिखने की आवश्यकता हो ।
back2dos

3
अपने आप से यह पूछें: क्या ऑपरेटर सिंटैक्टिक शुगर को ओवरलोड कर रहा है? उस प्रश्न का जो भी उत्तर आप सत्य मानते हैं, वह आपके द्वारा पूछे गए प्रश्न का उत्तर है;)
back2dos

5
@ back2dos: पूरी तरह से आपके साथ सहमत हैं। मैंने वाक्य पढ़ा "सब कुछ सिर्फ कोडांतरक के लिए सिंटैक्टिक शुगर है" बहुत बार, और यह स्पष्ट रूप से गलत है। कुछ मौजूदा सिंटैक्स के लिए सिंथेटिक शुगर एक वैकल्पिक (संभवतः अच्छे) सिंटैक्स है जो किसी भी नए शब्दार्थ को नहीं जोड़ता है।
जियोर्जियो

6
@ जियोर्जियो: सही है! अभिव्यक्ति पर मैथियास फेलिएसेन के लैंडमार्क पेपर में एक सटीक परिभाषा है। मूल रूप से: वाक्यात्मक चीनी शुद्ध रूप से स्थानीय है। यदि आपको भाषा सुविधा के उपयोग को हटाने के लिए कार्यक्रम की वैश्विक संरचना को बदलना है, तो यह वाक्यगत चीनी नहीं है। यानी कोडांतरक में बहुरूपी OO कोड को फिर से लिखने आम तौर पर वैश्विक प्रेषण तर्क है, जो जोड़ दिया जाता है नहीं पूरी तरह स्थानीय, इसलिए OO है नहीं "कोडांतरक के लिए बस वाक्यात्मक चीनी"।
जोर्ग डब्ल्यू मित्तग

जवाबों:


29

इसका उत्तर देने के लिए, आपको सबसे पहले "सिन्सेटिक शुगर" की परिभाषा चाहिए। मैं विकिपीडिया के साथ जाऊँगा :

कंप्यूटर विज्ञान में, वाक्य रचना चीनी एक प्रोग्रामिंग भाषा के भीतर वाक्यविन्यास है जो चीजों को पढ़ने या व्यक्त करने के लिए आसान बनाने के लिए डिज़ाइन किया गया है। यह मानव उपयोग के लिए भाषा को "मीठा" बनाता है: चीजों को अधिक स्पष्ट रूप से, अधिक संक्षिप्त रूप से, या एक वैकल्पिक शैली में व्यक्त किया जा सकता है जो कुछ पसंद कर सकते हैं।

[...]

विशेष रूप से, किसी भाषा में एक निर्माण को सिंटैक्टिक शुगर कहा जाता है यदि इसे भाषा से बिना किसी प्रभाव के हटाया जा सकता है तो भाषा क्या कर सकती है

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

इस परिभाषा के तहत विधि अधिभार, हालांकि, वाक्यविन्यास चीनी नहीं है, क्योंकि इसे हटाने से मौलिक रूप से भाषा बदल जाएगी (आप अब तर्क के आधार पर अलग व्यवहार के लिए भेजने में सक्षम नहीं होंगे)।

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


22
ओवरलोडिंग को हटाने से भाषा क्या कर सकती है, यह नहीं बदलता। आप अभी भी पहले की तरह ही चीजें कर सकते थे; आपको बस कुछ तरीकों का नाम बदलना होगा। लुप्त होती छोरों की तुलना में यह अधिक तुच्छ परिवर्तन है।
डोभाल

9
जैसा कि मैंने कहा, आप इस बात को ले सकते हैं कि सभी भाषाओं (मशीन भाषाओं सहित) में ट्यूरिंग मशीन के ऊपर सिंटैक्टिक शुगर है।
kdgregory

9
जैसा कि मैंने देखा है कि यह विधि ओवरलोडिंग की अनुमति देता है sum(numbersArray)और आप sum(numbersList)इसके बजाय sumArray(numbersArray)और करते हैं sumList(numbersList)। मैं डोभाल से सहमत हूं, यह मात्र चीनी की तरह लगता है।
अवीव कोहन

3
अधिकांश भाषा। को लागू करने का प्रयास करें instanceof, वर्ग, विरासत, इंटरफेस, जेनरिक, प्रतिबिंब या पहुँच विनिर्देशक का उपयोग कर if, whileऔर बूलियन ऑपरेटरों, साथ में ठीक उसी अर्थ विज्ञान । कोई कोने के मामले नहीं। ध्यान दें कि मैं आपको उन निर्माणों के विशिष्ट उपयोगों के समान चीजों की गणना करने के लिए चुनौती नहीं दे रहा हूं। मैं पहले से ही जानता हूं कि आप बूलियन लॉजिक और ब्रांचिंग / लूपिंग का उपयोग करके कुछ भी गणना कर सकते हैं। मैं आपसे उन भाषा विशेषताओं के शब्दार्थों की सही प्रतियाँ लागू करने के लिए कह रहा हूँ, जिसमें वे प्रदान की जाने वाली कोई भी स्थैतिक गारंटी शामिल है (संकलन समय की जाँच अभी भी संकलन समय पर ही की जानी चाहिए।)
डोभाल

6
@ डोवाल, kdgregory: सिंटैक्टिक शुगर को परिभाषित करने के लिए आपको इसे कुछ शब्दार्थों के सापेक्ष परिभाषित करना होगा। यदि आपके पास एकमात्र शब्दार्थ है "यह प्रोग्राम क्या गणना करता है?", तो यह स्पष्ट है कि एक ट्यूरिंग मशीन के लिए सब कुछ सिर्फ वाक्यगत चीनी है। दूसरी ओर, यदि आपके पास एक शब्दार्थ है जिसमें आप वस्तुओं और उन पर कुछ निश्चित संचालन के बारे में बोल सकते हैं, तो कुछ वाक्यविन्यास को हटाने से आप उन कार्यों को किसी भी अधिक व्यक्त नहीं कर पाएंगे, भले ही भाषा अभी भी ट्यूरिंग-पूर्ण हो सकती है।
जियोर्जियो

13

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

for(Object alpha: alphas) {
}

हो जाता है:

for(Iterator<Object> iter = alpha.iterator(); iter.hasNext()) {
   alpha = iter.next();
}

या चर तर्कों के साथ एक समारोह ले:

void foo(int... args);

foo(3, 4, 5);

जो बन जाता है:

void Foo(int[] args);

foo(new int[]{3, 4, 5});

तो अन्य सुविधाओं के संदर्भ में सुविधा को लागू करने के लिए वाक्यविन्यास का एक तुच्छ प्रतिस्थापन है।

चलो विधि अधिभार को देखो।

void foo(int a);
void foo(double b);

foo(4.5);

इसे फिर से लिखा जा सकता है:

void foo_int(int a);
void foo_double(double b);

foo_double(4.5);

लेकिन यह उसके बराबर नहीं है। जावा के मॉडल के भीतर, यह कुछ अलग है। बनाया जाने foo(int a)वाला foo_intफ़ंक्शन लागू नहीं करता है । जावा अस्पष्ट कार्यों को अजीब नाम देकर विधि अधिभार को लागू नहीं करता है। सिंथैटिक शुगर के रूप में गिनने के लिए, जावा को यह दिखावा करना होगा कि आपने वास्तव में लिखा है foo_intऔर foo_doubleकार्य करता है लेकिन ऐसा नहीं है।


2
मुझे नहीं लगता कि किसी ने कभी कहा कि वाक्यविन्यास चीनी के लिए परिवर्तन तुच्छ होना चाहिए। यहां तक ​​कि अगर यह किया है, मुझे लगता है कि But, the transformation isn't trivial. At the least, you have to determine the types of the parameters.बहुत स्केच का दावा है क्योंकि प्रकार निर्धारित करने की आवश्यकता नहीं है ; वे संकलन समय पर जाने जाते हैं।
डोभाल

3
"सिंटैक्टिक शुगर के रूप में गिनने के लिए, जावा को यह दिखावा करना होगा कि आपने वास्तव में foo_int और foo_double फ़ंक्शन लिखे हैं, लेकिन यह नहीं है।" - जब तक हम ओवरलोडिंग के तरीकों के बारे में बात करते हैं और बहुरूपताओं से नहीं, foo(int)/ foo(double)और foo_int/ के बीच क्या अंतर होगा foo_double? मैं वास्तव में जावा को बहुत अच्छी तरह से नहीं जानता, लेकिन मुझे लगता है कि इस तरह का नामकरण वास्तव में जेवीएम में होता है (अच्छी तरह से - शायद foo(args)तब उपयोग कर रहा है foo_args- यह कम से कम C ++ में प्रतीक के साथ काम करता है (ठीक है - प्रतीक पुतला तकनीकी रूप से एक कार्यान्वयन विवरण है और भाग नहीं है) भाषा का)।
मैकिज पाइचोटका

2
@ डोभाल: "मुझे नहीं लगता कि किसी ने कहा कि सिंटेक्स शुगर के लिए परिवर्तन को तुच्छ होना चाहिए।" - सच है, लेकिन यह स्थानीय होना चाहिए । वाक्यात्मक चीनी का ही उपयोगी परिभाषा मैं के बारे में पता भाषा expressivity पर मैथिअस फेलाइसेन के प्रसिद्ध कागज से है, और मूल रूप से यह कहा गया है कि यदि आप कर सकते हैं एक कार्यक्रम भाषा में लिखा फिर से लिखें एल + y (यानी कुछ भाषा एल कुछ सुविधा के साथ y में) भाषा L (यानी फीचर y के बिना उस भाषा का एक उपसमूह ) कार्यक्रम की वैश्विक संरचना को बदलने के बिना) (यानी केवल स्थानीय परिवर्तन कर रहा है), तो y L + y में वाक्यगत शर्करा है और करता है
जॉर्ग डब्ल्यू मित्तग

2
L की अभिव्यक्तता में वृद्धि नहीं । हालाँकि, यदि आप ऐसा नहीं कर सकते हैं , अर्थात यदि आपको अपने कार्यक्रम की वैश्विक संरचना में परिवर्तन करना है, तो यह वाक्यगत शर्करा नहीं है और वास्तव में L + y को L से अधिक अभिव्यंजक बनाती है । उदाहरण के लिए, एन्हांस्ड forलूप वाला जावा इसके बिना जावा से अधिक स्पष्ट नहीं है। (यह अच्छा है, अधिक संक्षिप्त, अधिक पठनीय है, और बेहतर चारों ओर, मैं बहस करूंगा, लेकिन अधिक अभिव्यंजक नहीं ।) मैं अतिभारित मामले के बारे में निश्चित नहीं हूं, हालांकि। मुझे यकीन है कि पेपर को दोबारा पढ़ना होगा। मेरे पेट में यह कहते है वाक्यात्मक चीनी, लेकिन मुझे यकीन नहीं कर रहा हूँ।
Jörg W Mittag

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

8

यह देखते हुए कि नाम-निर्माण कार्य करता है, क्या इसे सिंटैक्टिक चीनी से ज्यादा कुछ नहीं होना चाहिए?

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

दुर्भाग्य से, मैंने कभी भी किसी भाषा को ऐसा करते नहीं देखा। जब अस्पष्टता होती है, तो ये संकलक इसे हल नहीं करते हैं, वे जोर देते हैं कि लेखक उनके लिए इसे हल करता है।


आप जिस सुविधा की तलाश कर रहे हैं उसे "मल्टीपल डिस्पैच" कहा जाता है। हस्केल, स्काला और (4.0 के बाद से) C # सहित बहुत सी भाषाएं इसका समर्थन करती हैं।
इयान गैलोवे

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

2
मुझे लगता है कि आप गलत समझ रहे हैं। उदाहरण के लिए, C # में, यदि किसी विधि का कोई पैरामीटर है dynamicतो अधिभार संकल्प रनटाइम पर होता है, संकलन-समय पर नहीं । यही कारण है कि कई प्रेषण है, और यह कार्यों का नाम बदलकर दोहराया नहीं जा सकता।
इयान गैलोवे

काफी शांत। मैं अभी भी चर प्रकार के लिए परीक्षण कर सकता हूं, लेकिन यह अभी भी सिंटैक्टिक शुगर पर ओवरले किए गए एक अंतर्निहित फ़ंक्शन है। यह एक भाषा की विशेषता है, लेकिन केवल मुश्किल से।
जॉन जे ओबेरमार्क

7

भाषा के आधार पर, यह वाक्यगत शर्करा है या नहीं।

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

ध्यान दें कि डायनामिक डिस्पैच ओवरलोडिंग का एक रूप है, गतिशील रूप से कुछ मापदंडों पर हल किया गया है (कुछ भाषाओं के लिए केवल एक विशेष, यह , लेकिन सभी भाषाएं इतनी सीमित नहीं हैं), और मैं उस फॉर्म को ओवरएक्टिंग सिंटैक्टिक चीनी नहीं कहूंगा।


मुझे यकीन नहीं है कि अनिवार्य रूप से गलत होने पर अन्य उत्तर इतना बेहतर कैसे कर रहे हैं।
तेलस्टिन

5

समकालीन भाषाओं के लिए, यह सिंटैक्टिक शुगर है; पूरी तरह से भाषा-अज्ञेय प्रकार में, यह उससे कहीं अधिक है।

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

यहां यह अधिक क्यों होना चाहिए।

ऐसी भाषा पर विचार करें जो ओवरलोडिंग और अनपेड चर दोनों तरीकों का समर्थन करती है। आप निम्न विधि प्रोटोटाइप हो सकते हैं:

bool someFunction(int arg);

bool someFunction(string arg);

कुछ भाषाओं में, आपको संभवतः संकलन के समय यह जानने के लिए इस्तीफा दे दिया जाएगा कि इनमें से किसी एक को कोड की एक पंक्ति कहा जाएगा। लेकिन कुछ भाषाओं में, सभी वेरिएबल्स टाइप नहीं होते हैं (या वे सभी निहित रूप से Objectया जो भी टाइप किए जाते हैं ), इसलिए एक ऐसे शब्दकोश के निर्माण की कल्पना करें, जिसकी कुंजी विभिन्न प्रकारों के मानों के लिए तैयार हो:

dict roomNumber; // some hotels use numbers, some use letters, and some use
                 // alphanumerical strings.  In some languages, built-in dictionary
                 // types automatically use untyped values for their keys to map to,
                 // so it makes more sense then to allow for both ints and strings in
                 // your code.

अब तब, यदि आप someFunctionउन कमरों में से किसी एक पर आवेदन करना चाहते हैं, तो क्या होगा ? आप इसे कॉल करें:

someFunction(roomNumber[someSortOfKey]);

है someFunction(int)कहा जाता है, या है someFunction(string)कहा जाता है? यहां आप एक उदाहरण देखते हैं जहां ये पूरी तरह से रूढ़िवादी तरीके नहीं हैं, खासकर उच्च-स्तरीय भाषाओं में। भाषा का पता लगाना है - रनटाइम के दौरान - इनमें से किसे कॉल करना है, इसलिए इसे अभी भी कम से कम कुछ हद तक एक ही तरीका माना जा रहा है।

क्यों नहीं बस टेम्पलेट्स का उपयोग करें? क्यों नहीं बस एक अनकही बहस का उपयोग करें?

लचीलापन और महीन दानेदार नियंत्रण। कभी-कभी टेम्प्लेट / अनकैप्ड तर्कों का उपयोग करना एक बेहतर दृष्टिकोण होता है, लेकिन कभी-कभी वे नहीं होते हैं।

आपको उन मामलों के बारे में सोचना होगा जहां, उदाहरण के लिए, आपके पास दो तरीके के हस्ताक्षर हो सकते हैं जो प्रत्येक intएक stringतर्क के रूप में लेते हैं , लेकिन जहां प्रत्येक हस्ताक्षर में आदेश अलग है। ऐसा करने के लिए आपके पास बहुत अच्छा कारण हो सकता है, क्योंकि प्रत्येक हस्ताक्षर का कार्यान्वयन बड़े पैमाने पर एक ही काम कर सकता है, लेकिन बस थोड़ा अलग मोड़ के साथ; उदाहरण के लिए लॉगिंग अलग हो सकती है। या यहां तक ​​कि अगर वे एक ही सटीक काम करते हैं, तो आप केवल उस आदेश से कुछ जानकारी को स्वचालित रूप से चमकाने में सक्षम हो सकते हैं जिसमें तर्क निर्दिष्ट किए गए थे। तकनीकी रूप से आप सिर्फ छद्म-स्विच स्टेटमेंट का उपयोग कर सकते हैं, जिसमें पारित किए गए प्रत्येक तर्क के प्रकार को निर्धारित करने के लिए, लेकिन यह गड़बड़ हो जाता है।

तो क्या यह अगला उदाहरण खराब प्रोग्रामिंग अभ्यास है?

bool stringIsTrue(int arg)
{
    if (arg.toString() == "0")
    {
        return false;
    }
    else
    {
        return true;
    }
}

bool stringIsTrue(Object arg)
{
    if (arg.toString() == "0")
    {
        return false;
    }
    else
    {
        return true;
    }
}

bool stringIsTrue(string arg)
{
    if (arg == "0")
    {
        return false;
    }
    else
    {
        return true;
    }
}

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

bool stringIsTrue(untyped arg)
{
    if (arg.toString() == "0")
    {
        return false;
    }
    else
    {
        return true;
    }
}

लेकिन क्या होगा यदि आपको केवल intएस और stringएस के लिए इसका उपयोग करने की आवश्यकता है , और क्या होगा यदि आप चाहते हैं कि यह सरल या अधिक जटिल परिस्थितियों के आधार पर सही वापस लौटे? फिर आपके पास ओवरलोडिंग का उपयोग करने का एक अच्छा कारण है:

bool appearsToBeFirstFloor(int arg)
{
    if (arg.digitAt(0) == 1)
    {
        return true;
    }
    else
    {
        return false;
    }
}

bool appearsToBeFirstFloor(string arg)
{
    string firstCharacter = arg.characterAt(0);
    if (firstCharacter.isDigit())
    {
        return appearsToBeFirstFloor(int(firstCharacter));
    }
    else if (firstCharacter.toUpper() == "A")
    {
        return true;
    }
    else
    {
        return false;
    }
}

लेकिन हे, क्यों न केवल उन कार्यों को दो अलग-अलग नाम दिए जाएं? आप अभी भी ठीक-ठीक नियंत्रण की एक ही राशि है, है ना?

क्योंकि, जैसा कि पहले कहा गया है, कुछ होटल संख्याओं का उपयोग करते हैं, कुछ पत्र का उपयोग करते हैं, और कुछ संख्याओं और अक्षरों के मिश्रण का उपयोग करते हैं:

appearsToBeFirstFloor(roomNumber[someSortOfKey]);

// will treat ints and strings differently, without you having to write extra code
// every single spot where the function is being called

यह अभी भी ठीक वही सटीक कोड नहीं है जिसका मैं वास्तविक जीवन में उपयोग करूंगा, लेकिन यह उस बिंदु को स्पष्ट करना चाहिए जिसे मैं अभी ठीक कर रहा हूं।

लेकिन ... यहाँ यह समकालीन भाषाओं में चीनी से अधिक नहीं है।

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

जैसा कि आप जानते हैं, ActionScript 3 विधि ओवरलोडिंग का समर्थन नहीं करता है। VB.NET के लिए, आप स्पष्ट रूप से एक प्रकार बताए बिना चर घोषित कर सकते हैं और सेट कर सकते हैं, लेकिन जब आप इन चर को ओवरलोड तरीकों से तर्क के रूप में पारित करने का प्रयास करते हैं, तो यह अभी भी रनटाइम मान को पढ़ने के लिए नहीं निर्धारित करता है कि किस विधि को कॉल करना है; इसके बजाय वह प्रकार के तर्कों के साथ एक विधि खोजना चाहता है Objectया कोई प्रकार या ऐसा कुछ नहीं है। तो intबनाम stringउपरोक्त उदाहरण उस भाषा में काम नहीं होता या तो। C ++ में इसी तरह के मुद्दे हैं, जैसे कि जब आप एक शून्य पॉइंटर या उस जैसे कुछ अन्य तंत्र का उपयोग करते हैं, तब भी आपको संकलन समय पर मैन्युअल रूप से इस प्रकार की आवश्यकता होती है।

तो जैसा कि पहले हेडर कहता है ...

समकालीन भाषाओं के लिए, यह सिंटैक्टिक शुगर है; पूरी तरह से भाषा-अज्ञेय प्रकार में, यह उससे कहीं अधिक है। उपर्युक्त उदाहरण की तरह, अधिक उपयोगी और प्रासंगिक बनाने की विधि बनाना, वास्तव में मौजूदा भाषा में जोड़ने के लिए एक अच्छी सुविधा हो सकती है (जैसा कि एएस 3 के लिए व्यापक रूप से अनुरोध किया गया है), या यह कई अलग-अलग मूलभूत स्तंभों में से एक के रूप में भी काम कर सकता है। एक नई प्रक्रियात्मक / वस्तु-उन्मुख भाषा का निर्माण।


3
क्या आप किसी भी भाषा को नाम दे सकते हैं जो वास्तव में फ़ंक्शन-डिस्पैच को रनटाइम पर संभालती है और संकलन-समय पर नहीं? सभी भाषाओं को मैं जानता हूं कि संकलन-समय की निश्चितता किस फ़ंक्शन को कहा जाता है ...
फाल्को

@Falco ActionScript 3.0 इसे रनटाइम पर हैंडल करता है। तुम्हें पता है, उदाहरण के लिए, एक समारोह का उपयोग कर सकता है कि रिटर्न यादृच्छिक पर तीन तार में से एक है, और फिर अपनी वापसी मान का उपयोग यादृच्छिक पर तीन कार्यों में से किसी एक कॉल करने के लिए: this[chooseFunctionNameAtRandom](); अगर chooseFunctionNameAtRandom()रिटर्न या तो "punch", "kick"या "dodge", तो आप thusly एक बहुत ही सरल यादृच्छिक लागू कर सकते हैं उदाहरण के लिए, फ़्लैश खेल में एक दुश्मन का एआई।
पैन्ज़रक्रिसिस

1
हां - लेकिन वे दोनों गतिशील फ़ंक्शन प्रेषण पाने के लिए वास्तविक अर्थ विधियां हैं, जावा के पास ये भी हैं। लेकिन वे ओवरलोडिंग से भिन्न होते हैं, ओवरलोडिंग स्थिर और बस वाक्यात्मक चीनी होती है, जबकि गतिशील प्रेषण और विरासत वास्तविक भाषा की विशेषताएं हैं, जो नई कार्यक्षमता प्रदान करती हैं!
फाल्को

1
... मैंने सी ++ में शून्य पॉइंटर्स के साथ-साथ बेस क्लास पॉइंटर्स की भी कोशिश की, लेकिन कंपाइलर चाहता था कि मैं इसे फंक्शन में पास करने से पहले खुद को डिसएब्यू कर लूं। तो अब मैं सोच रहा हूँ कि क्या इस उत्तर को हटाऊं। यह देखने में ऐसा लगने लगा है कि समान निर्देश या कथन में फ़ंक्शन ओवरलोडिंग के साथ डायनामिक फंक्शन च्वाइस के संयोजन के लिए भाषाएं लगभग हमेशा सही चलती हैं, लेकिन फिर अंतिम सेकंड में दूर जाती हैं। हालांकि यह एक अच्छी भाषा सुविधा होगी; हो सकता है कि किसी को ऐसी भाषा बनाने की आवश्यकता हो, जिसमें यह हो।
पैंजरक्रिस

1
उत्तर को रुकने दें, हो सकता है कि उत्तर में टिप्पणियों से अपने कुछ शोधों को शामिल करने के बारे में सोचें?
फाल्को

2

यह वास्तव में "सिंटैक्टिक शुगर" के आपके दृष्टिकोण से निर्भर करता है। मैं अपने दिमाग में आने वाली कुछ परिभाषाओं को संबोधित करने की कोशिश करूंगा:

  1. एक सुविधा वाक्यविन्यास चीनी है जब एक प्रोग्राम जो इसका उपयोग करता है उसे हमेशा दूसरे में अनुवादित किया जा सकता है जो सुविधा का उपयोग नहीं करता है।

    यहाँ हम मान रहे हैं कि सुविधाओं का एक आदिम सेट मौजूद है जिसका अनुवाद नहीं किया जा सकता है: दूसरे शब्दों में इस तरह का कोई लूप नहीं है "आप फीचर Y का उपयोग कर फीचर X को बदल सकते हैं" और "आप फीचर Y को फीचर X से बदल सकते हैं"। यदि दोनों में से कोई एक या तो सही है तो अन्य फीचर को उन विशेषताओं के संदर्भ में व्यक्त किया जा सकता है जो पहले एक नहीं हैं या यह एक आदिम सुविधा है।

  2. 1 परिभाषा के रूप में ही, लेकिन अतिरिक्त आवश्यकता के साथ कि अनुवादित कार्यक्रम पहले की तरह टाइप-सुरक्षित है, अर्थात नीचे उतरकर आप किसी भी प्रकार की जानकारी को ढीला नहीं करते हैं।

  3. ओपी की परिभाषा: एक विशेषता वाक्यगत शर्करा है यदि इसका अनुवाद कार्यक्रम की संरचना को नहीं बदलता है, लेकिन केवल "स्थानीय परिवर्तन" की आवश्यकता होती है।

ओवरलोडिंग के लिए उदाहरण के रूप में हास्केल को लेते हैं। हास्केल उपयोगकर्ता-परिभाषित ओवरलोडिंग को प्रकार की कक्षाओं के माध्यम से प्रदान करता है। उदाहरण के लिए +और *ऑपरेशन्स को Numटाइप क्लास में परिभाषित किया जाता है और किसी भी प्रकार में ऐसी क्लास का पूरा (पूर्ण) उदाहरण इस्तेमाल किया जा सकता है +। उदाहरण के लिए:

instance Num a => Num (b, a) where
    (x, y) + (_, y') = (x, y + y')
    -- other definitions

("Hello", 1) + ("World", 3) -- -> ("Hello", 4)

हास्केल के प्रकार वर्गों के बारे में एक प्रसिद्ध बात यह है कि आप उनसे छुटकारा पा सकते हैं । यानी आप किसी भी प्रोग्राम को टाइप कर सकते हैं जो एक समान प्रोग्राम में टाइप क्लास का उपयोग करता है जो उनका उपयोग नहीं करता है।

अनुवाद काफी सरल है:

  • एक वर्ग परिभाषा दी:

    class (P_1 a, ..., P_n a) => X a where
        op_1 :: t_1   ... op_m :: t_m
    

    आप इसे एक बीजीय डेटा प्रकार में अनुवाद कर सकते हैं:

    data X a = X {
        X_P_1 :: P_1 a, ... X_P_n :: P_n a,
        X_op_1 :: t_1, ..., X_op_m :: t_m
    }
    

    यहाँ के X_P_iऔर X_op_iहैं चयनकर्ताओं । Ie को मान पर X aलागू X_P_1करने का प्रकार दिया गया है, उस क्षेत्र में संग्रहीत मान लौटाएगा, इसलिए वे प्रकार X a -> P_i a(या X a -> t_i) के साथ कार्य करते हैं ।

    एक के लिए बहुत किसी न किसी anology आप प्रकार के लिए मूल्यों के बारे में सोच सकता है X aके रूप में structहै और फिर अगर xइस प्रकार का है X aभाव:

    X_P_1 x
    X_op_1 x
    

    के रूप में देखा जा सकता है:

    x.X_P_1
    x.X_op_1
    

    (नामित फ़ील्ड के बजाय केवल स्थितीय फ़ील्ड का उपयोग करना आसान है, लेकिन नामित फ़ील्ड उदाहरणों में संभालना आसान है और कुछ बॉयलर-प्लेट बॉक्स से बचना है)।

  • एक उदाहरण घोषणा को देखते हुए:

    instance (C_1 a_1, ..., C_n a_n) => X (T a_1 ... a_n) where
        op_1 = ...; ...;  op_m = ...
    

    आप इसे एक ऐसे फंक्शन में अनुवाद कर सकते हैं, जो C_1 a_1, ..., C_n a_nवर्गों के लिए डिक्शनरी देता है, टाइप के X aलिए एक डिक्शनरी वैल्यू (यानी वैल्यू ऑफ टाइप ) देता है T a_1 ... a_n

    दूसरे शब्दों में उपरोक्त उदाहरण को एक फ़ंक्शन में अनुवादित किया जा सकता है जैसे:

    f :: C_1 a_1 -> ... -> C_n a_n -> X (T a_1 ... a_n)
    

    (ध्यान दें कि nहो सकता है 0)।

    और वास्तव में हम इसे इस प्रकार परिभाषित कर सकते हैं:

    f c1 ... cN = X {X_P_1=get_P_1_T, X_P_n=get_P_n_T,
                     X_op_1=op_1, ..., X_op_m=op_m}
        where
            op_1 = ...
            ...
            op_m = ...
    

    जहां op_1 = ...के लिए op_m = ...परिभाषाओं में पाए जाते हैं instanceघोषणा और get_P_i_Tकार्यों द्वारा परिभाषित कर रहे हैं P_iके कहने Tका प्रकार (इन क्योंकि मौजूद होना चाहिए P_iके सुपर-क्लास हैं X)।

  • एक अधिभार समारोह के लिए एक कॉल दिया:

    add :: Num a => a -> a -> a
    add x y = x + y
    

    हम स्पष्ट रूप से वर्ग बाधाओं के सापेक्ष शब्दकोशों को पास कर सकते हैं और एक बराबर कॉल प्राप्त कर सकते हैं:

    add :: Num a -> a -> a -> a
    add dictNum x y = ((+) dictNum) x y
    

    ध्यान दें कि कैसे वर्ग की बाधाएं बस एक नया तर्क बन गईं। +अनुवाद कार्यक्रम में चयनकर्ता के रूप में पहले समझाया है। दूसरे शब्दों में अनुवादित addफ़ंक्शन, इसके तर्क के प्रकार के लिए दिया गया शब्दकोश पहले परिणाम का उपयोग करने की गणना करने के लिए वास्तविक फ़ंक्शन को "अनपैक" (+) dictNumकरेगा और फिर इस फ़ंक्शन को तर्कों पर लागू करेगा।

यह पूरी बात के बारे में एक बहुत ही त्वरित स्केच है। यदि आप रुचि रखते हैं तो आपको साइमन पेटन जोन्स एट अल के लेखों को पढ़ना चाहिए।

मेरा मानना ​​है कि इसी तरह के दृष्टिकोण का इस्तेमाल अन्य भाषाओं में भी ओवरलोडिंग के लिए किया जा सकता है।

हालाँकि यह दर्शाता है कि, यदि आपकी वाक्यात्मक शर्करा की परिभाषा (1) है, तो अतिभार संश्लिष्ट शर्करा है । क्योंकि आप इससे छुटकारा पा सकते हैं।

हालाँकि अनुवादित कार्यक्रम मूल कार्यक्रम के बारे में कुछ जानकारी खो देता है। उदाहरण के लिए यह लागू नहीं करता है कि मूल वर्गों के लिए उदाहरण मौजूद हैं। (हालांकि, माता-पिता के शब्दकोशों को निकालने के लिए संचालन अभी भी उस प्रकार का होना चाहिए, आप undefinedया अन्य बहुरूपी मानों को पारित कर सकते हैं ताकि आप मानों का निर्माण X yकिए बिना एक मान बना P_i yसकें, इसलिए अनुवाद सभी को ढीला नहीं करता है। प्रकार सुरक्षा)। इसलिए यह (2) के अनुसार चीनी नहीं है

के रूप में (3)। मुझे नहीं पता कि जवाब हां या ना में होना चाहिए।

मैं नहीं कहूंगा क्योंकि, उदाहरण के लिए, एक उदाहरण घोषणा एक फ़ंक्शन परिभाषा बन जाती है। ओवरलोड किए गए फ़ंक्शंस को एक नया पैरामीटर मिलता है (जिसका अर्थ है कि यह परिभाषा और सभी कॉल दोनों को बदलता है)।

मैं हाँ कहूँगा क्योंकि दो प्रोग्राम अभी भी एक-से-एक मैप करते हैं, इसलिए "संरचना" वास्तव में इतना नहीं बदला है।


इसने कहा, मैं कहूंगा कि अधिभार द्वारा शुरू किए गए व्यावहारिक लाभ इतने बड़े हैं कि "व्युत्पन्न" शब्द जैसे कि "सिटैक्टिक शुगर" का उपयोग करना सही नहीं लगता है।

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


2

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

जब भी आप किसी चर के प्रकार को बदलते हैं, तो आपके द्वारा कॉल की जाने वाली विधियों के नाम को बदलना एक उपद्रव होगा, लेकिन उदाहरण के लिए C भाषा में इसे एक प्रबंधनीय उपद्रव माना जाता है, इसलिए C में कार्य अतिभार नहीं है (हालाँकि यह अब सामान्य मैक्रो है)।

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

जावा में आप कितने भार के वहाँ के हैं, उदाहरण के लिए विचार कर सिर्फ एक सुविधा की तुलना में अधिक यह सोच सकते हैं PrintStream.printऔर PrintStream.println। लेकिन फिर भी, वहाँ कई DataInputStream.readXतरीके हैं क्योंकि जावा रिटर्न प्रकार पर अधिभार नहीं डालता है, इसलिए कुछ अर्थों में यह सिर्फ सुविधा के लिए है। वे सभी आदिम प्रकार के हैं।

मुझे याद नहीं क्या जावा में होता है अगर मैं श्रेणियां होती हैं Aऔर Bविस्तार O, मैं तरीकों को ओवरलोड foo(O), foo(A)और foo(B)एक सामान्य में, और उसके बाद से <T extends O>मैं फोन foo(t)जहां tका एक उदाहरण है T। इस मामले में जहां में Tहै Aमैं अधिभार के आधार पर प्रेषण मिलता है या यह कि अगर मैं कहा जाता है के रूप में है foo(O)?

यदि पूर्व, तो जावा विधि अधिभार उसी तरह चीनी से बेहतर है जिस तरह से सी ++ अधिभार हैं। आपकी परिभाषा का उपयोग करते हुए, मुझे लगता है कि मैं जावा में स्थानीय प्रकार की जांचों की एक श्रृंखला लिख ​​सकता हूं (जो नाजुक होगी, क्योंकि नए ओवरलोड को fooअतिरिक्त जांच की आवश्यकता होगी)। इस बात को स्वीकार करने के अलावा कि मैं इसे सही होने के लिए कॉल साइट पर स्थानीय परिवर्तन नहीं कर सकता , इसके बजाय मुझे जेनेरिक कोड लिखना छोड़ना होगा। मेरा तर्क है कि ब्लोटेड कोड को रोकने के लिए सिंटैक्टिक शुगर हो सकती है, लेकिन नाजुक कोड को रोकना इससे अधिक है। उस कारण से, सामान्य रूप से स्थैतिक बहुरूपता सिंटैक्टिक शुगर से अधिक है। किसी विशेष भाषा की स्थिति भिन्न हो सकती है, यह इस बात पर निर्भर करता है कि भाषा आपको कितनी दूर तक स्थिर प्रकार का "पता नहीं" करने की अनुमति देती है।


जावा में, अधिभार को संकलन समय पर हल किया जाता है। प्रकार के क्षरण के उपयोग को देखते हुए, अन्यथा उनके लिए यह असंभव होगा। इसके अलावा, भले प्रकार विलोपन के बिना, अगर T:Animalप्रकार है है SiameseCatऔर मौजूदा भार के कर रहे हैं Cat Foo(Animal), SiameseCat Foo(Cat)और Animal Foo(SiameseCat), जो अधिभार यदि चयनित किया जाना चाहिए Tहै SiameseCat?
सुपरकैट

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

ओवरलोड ऐसे मामलों में मददगार हो सकते हैं, जहां तरीकों के वैकल्पिक तर्क होते हैं, लेकिन वे खतरनाक भी हो सकते हैं। मान लीजिए कि रेखा long foo=Math.round(bar*1.0001)*5बदल जाती है long foo=Math.round(bar)*5। अगर यह bar, 123456789L के बराबर होता है, तो यह शब्दार्थ को कैसे प्रभावित करेगा ?
सुपरकैट

@supercat मैं वास्तविक खतरे का तर्क दूंगा कि इसमें निहित रूपांतरण longहै double
डोभाल

@ डोभाल: को double?
19 अक्टूबर को सुपरकैट

1

यह ऐसा लगता है जैसे "सिंटैक्टिक शुगर" अपमानजनक या बेकार लगता है। यही कारण है कि सवाल कई नकारात्मक उत्तरों को ट्रिगर करता है।

लेकिन आप सही हैं, विभिन्न तरीकों के लिए एक ही नाम का उपयोग करने की संभावना को छोड़कर, विधि अधिभार भाषा में कोई सुविधा नहीं जोड़ता है। आप पैरामीटर प्रकार को स्पष्ट कर सकते हैं, प्रोग्राम अभी भी उसी तरह काम करेगा।

पैकेज के नामों पर भी यही लागू होता है। स्ट्रिंग java.lang.String के लिए सिंटैक्टिक शुगर है।

वास्तव में, एक विधि की तरह

void fun(int i, String c);

वर्ग में MyClass को "my_package_MyClass_fun_int_java_lang_String" कहा जाना चाहिए। यह विशिष्ट विधि की पहचान करेगा। (JVM आंतरिक रूप से ऐसा कुछ करता है)। लेकिन आप ऐसा नहीं लिखना चाहते हैं। यही कारण है कि संकलक आपको मजेदार (1, "एक") लिखने देगा और यह पहचान करेगा कि यह कौन सी विधि है।

हालांकि एक चीज है जिसे आप ओवरलोडिंग के साथ कर सकते हैं: यदि आप एक ही संख्या के तर्कों के साथ एक विधि को अधिभारित करते हैं, तो संकलक स्वचालित रूप से यह पता लगाएगा कि कौन से संस्करण समान तर्कों के साथ दिए गए तर्क से दिए गए तर्क को सबसे अच्छी तरह से सूट करते हैं, न केवल समान प्रकार के साथ, बल्कि जहां भी दिया गया तर्क घोषित तर्क का एक उपवर्ग है।

यदि आपके पास दो अधिभार प्रक्रियाएं हैं

addParameter(String name, Object value);
addParameter(String name, Date value);

आपको यह जानने की आवश्यकता नहीं है कि दिनांक के लिए प्रक्रिया का एक विशिष्ट संस्करण है। addParameter ("hello", "world) पहला वर्जन कहेगा, addParameter (" now ", new Date) () दूसरा कॉल करेगा।

बेशक, आपको दूसरी विधि के साथ एक विधि को ओवरलोड करने से बचना चाहिए जो पूरी तरह से अलग काम करता है।


1

दिलचस्प है, इस सवाल का जवाब भाषा पर निर्भर करेगा।

विशेष रूप से, ओवरलोडिंग और जेनेरिक प्रोग्रामिंग (*) के बीच एक अंतःक्रिया होती है , और इस बात पर निर्भर करता है कि जेनेरिक प्रोग्रामिंग कैसे कार्यान्वित की जाती है, यह सिंटैक्टिक शुगर (जंग) या बिल्कुल आवश्यक (C ++) हो सकती है।

यही है, जब जेनेरिक प्रोग्रामिंग को स्पष्ट इंटरफेस (रस्ट या हास्केल में, उन प्रकार के वर्ग होंगे) के साथ लागू किया जाता है , तो ओवरलोडिंग सिर्फ वाक्यगत चीनी है; या वास्तव में भाषा का हिस्सा भी नहीं हो सकता है।

दूसरी ओर, जब सामान्य प्रोग्रामिंग को डक-टाइपिंग के साथ लागू किया जाता है (यह गतिशील या स्थिर हो) के तो विधि का नाम एक आवश्यक अनुबंध है, और इसलिए सिस्टम को काम करने के लिए ओवरलोडिंग अनिवार्य है।

(*) एक बार एक विधि लिखने के अर्थ में, एक समान फैशन में विभिन्न प्रकारों को संचालित करने के लिए उपयोग किया जाता है।


0

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

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

उपयोग को प्रतिस्थापित करने के लिए बहुत कठिन का एक उदाहरण एक ऐसी भाषा से आता है जो विडंबना यह है कि इस सुविधा को "फ़ंक्शन ओवरलोडिंग" नहीं कहा जाता है। इसके बजाय इसे "पैटर्न मिलान" कहा जाता है (जिसे ओवरलोडिंग के सुपरसेट के रूप में देखा जा सकता है क्योंकि हम न केवल प्रकार बल्कि मूल्यों को अधिभार कर सकते हैं)।

यहां हास्केल में फिबोनाची फ़ंक्शन का क्लासिक भोला कार्यान्वयन है:

fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)

तर्कत: तीनों कार्यों को किसी अन्य के साथ बदल दिया जा सकता है, जैसा कि सामान्यतः किसी अन्य भाषा में किया जाता है। लेकिन यह मूल रूप से पूरी तरह से सरल परिभाषा बनाता है:

fib n = fib (n-1) + fib (n-2)

बहुत गड़बड़ है और सीधे फाइबोनैचि अनुक्रम की गणितीय धारणा को व्यक्त नहीं करता है।

तो कभी-कभी यह वाक्यविन्यास चीनी हो सकता है यदि एकमात्र उपयोग आपको विभिन्न तर्कों के साथ एक फ़ंक्शन को कॉल करने की अनुमति देता है। लेकिन कभी-कभी यह उससे कहीं अधिक मौलिक होता है।


अब ऑपरेटर के ओवरलोडिंग के लिए चीनी के लिए क्या हो सकता है, इस बात का खुलासा करना होगा। आपने एक उपयोग-मामले की पहचान की है - इसका उपयोग समान कार्यों को लागू करने के लिए किया जा सकता है जो विभिन्न तर्क लेते हैं। इसलिए:

function print (string x) { stdout.print(x) };
function print (number x) { stdout.print(x.toString) };

वैकल्पिक रूप से लागू किया जा सकता है:

function printString (string x) {...}
function printNumber (number x) {...}

या और भी:

function print (auto x) {
    if (x instanceof String) {...}
    if (x instanceof Number) {...}
}

लेकिन ऑपरेटर ओवरलोडिंग भी वैकल्पिक तर्कों को लागू करने के लिए एक चीनी हो सकती है (कुछ भाषाओं में ऑपरेटर ओवरलोडिंग है लेकिन वैकल्पिक तर्क नहीं हैं):

function print (string x) {...}
function print (string x, stream io) {...}

लागू करने के लिए इस्तेमाल किया जा सकता है:

function print (string x, stream io=stdout) {...}

ऐसी भाषा में (google "फेराइट भाषा") ऑपरेटर को ओवरलोडिंग को हटाने से एक सुविधा - वैकल्पिक तर्कों को हटा दिया जाता है। दोनों विशेषताओं के साथ भाषाओं में दी गई (c ++) एक या दूसरे को हटाने का कोई शुद्ध प्रभाव नहीं होगा क्योंकि या तो वैकल्पिक तर्कों को लागू करने के लिए उपयोग किया जा सकता है।


हास्केल इस बात का एक अच्छा उदाहरण है कि ऑपरेटर ओवरलोडिंग सिंटैक्टिक शुगर क्यों नहीं है, लेकिन मुझे लगता है कि एक बेहतर उदाहरण पैटर्न मिलान के साथ बीजीय डेटा प्रकार को डिकॉन्स्ट्रक्ट करना होगा (कुछ ऐसा है जो पैटर्न मिलान के बिना असंभव है)।
11684

@ 11684: क्या आप एक उदाहरण की ओर इशारा कर सकते हैं? मैं ईमानदारी से हास्केल को बिल्कुल नहीं जानता, लेकिन जब मैंने उस फ़ाइबर उदाहरण (यूट्यूब पर कंप्यूटरफाइल पर) को देखा, तो इसका पैटर्न बेहद सुंदर मिला।
स्लीपबेटमैन

data PaymentInfo = CashOnDelivery | Adress String | UserInvoice CustomerInfoआप जैसे डेटासाइप को देखते हुए टाइप कंस्ट्रक्टर्स पर मैच कर सकते हैं।
11684

इस तरह getPayment :: PaymentInfo -> a getPayment CashOnDelivery = error "Should have been paid already" getPayment (Adress addr) = -- code to notify administration to send a bill getPayment (UserInvoice cust) = --whatever. I took the data type from a Haskell tutorial and have no idea what an invoice is:। मुझे उम्मीद है कि यह टिप्पणी कुछ समझ में आने वाली है।
1568 पर 11684

0

मुझे लगता है कि यह ज्यादातर भाषाओं में सरल वाक्यगत चीनी है (कम से कम सभी मुझे पता है ...) क्योंकि इन सभी को संकलन समय पर एक अस्पष्ट फ़ंक्शन-कॉल की आवश्यकता होती है। और कंपाइलर केवल फ़ंक्शन कॉल को एक स्पष्ट पॉइंटर के साथ सही कार्यान्वयन हस्ताक्षर में बदल देता है।

जावा में उदाहरण:

String s; int i;
mangle(s);  // Translates to CALL ('mangle':LString):(s)
mangle(i);  // Translates to CALL ('mangle':Lint):(i)

तो अंत में इसे पूरी तरह से एक साधारण कंपाइलर-मैक्रो द्वारा खोज और प्रतिस्थापित करने के साथ बदल दिया जा सकता है, मैनलोड_स्ट्रिंग और मैंगले_इंट के साथ ओवरलोड फंक्शन मैनल की जगह - चूंकि तर्क-सूची अंतिम फ़ंक्शन-आइडेंटिफ़ायर का हिस्सा है, क्योंकि यह व्यावहारिक रूप से होता है -> और ( इसलिए यह केवल कृत्रिम चीनी है।

अब अगर कोई भाषा है, जहां फ़ंक्शन रनटाइम पर वास्तव में निर्धारित किया जाता है, जैसे ऑब्जेक्ट्स में ओवरराइड मैथड्स के साथ, यह अलग होगा। लेकिन मुझे नहीं लगता कि ऐसी कोई भाषा है, क्योंकि method.overloading में अस्पष्टता है, जिसे कंपाइलर हल नहीं कर सकता है और जिसे प्रोग्रामर द्वारा एक स्पष्ट कलाकार के साथ हैंडल किया जाना है। यह रनटाइम पर नहीं किया जा सकता है।


0

जावा प्रकार में जानकारी संकलित की जाती है और ओवरलोड में से कौन सा कहा जाता है, संकलन समय पर तय होता है।

निम्नलिखित sun.misc.Unsafeग्रहण (एटॉमिक्स के लिए उपयोगिता) से एक स्निपेट है जैसा कि एक्लिप्स के क्लास फाइल एडिटर में देखा गया है।

  // Method descriptor #143 (Ljava/lang/Object;I)I (deprecated)
  // Stack: 4, Locals: 3
  @java.lang.Deprecated
  public int getInt(java.lang.Object arg0, int arg1);
    0  aload_0 [this]
    1  aload_1 [arg0]
    2  iload_2 [arg1]
    3  i2l
    4  invokevirtual sun.misc.Unsafe.getInt(java.lang.Object, long) : int [231]
    7  ireturn
      Line numbers:
        [pc: 0, line: 213]

जैसा कि आप कॉल की जाने वाली विधि की टाइप जानकारी देख सकते हैं (पंक्ति 4) कॉल में शामिल है।

इसका मतलब है कि आप एक जावा कंपाइलर बना सकते हैं जो टाइप जानकारी लेता है। उदाहरण के लिए इस तरह के एक संकेतन का उपयोग करके उपरोक्त स्रोत होगा:

@Deprecated
public in getInt(Object arg0, int arg1){
     return getInt$(Object,long)(arg0, arg1);
}

और कास्ट टू लॉन्ग वैकल्पिक होगा।

अन्य सांख्यिकीय रूप से संकलित भाषाओं में आपको एक समान सेटअप दिखाई देगा जहां कंपाइलर तय करेगा कि कौन सा अधिभार टाइप के आधार पर बुलाया जाएगा और इसे बाइंडिंग / कॉल में शामिल किया जाएगा।

अपवाद सी डायनेमिक लाइब्रेरी है जहां प्रकार की जानकारी शामिल नहीं है और एक अतिभारित फ़ंक्शन बनाने की कोशिश करने से लिंकर को शिकायत होगी।

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