2014-07-17 7 views
5

मैंने अक्सर पढ़ा है कि जावा वाइल्डकार्ड एक अवधारणा है जो उपयोग-साइट भिन्नता की अवधारणा से अधिक शक्तिशाली है। लेकिन मेरी समझ में, जावा वाइल्डकार्ड की अवधारणा के बराबर है जो साइट-साइट भिन्नता की अवधारणा है।जावा वाइल्डकार्ड उपयोग-साइट भिन्नता से अधिक शक्तिशाली क्यों हैं?

तो दोनों के बीच क्या अंतर है? क्या आप एक ठोस उदाहरण दे सकते हैं जो जावा वाइल्डकार्ड के साथ संभव है लेकिन उपयोग साइट भिन्नता के साथ नहीं?

उदाहरण के लिए, How does Java's use-site variance compare to C#'s declaration site variance? के पहले उत्तर एक उदाहरण है जहाँ मेरे सवाल का दावा किया जाता है:

सबसे पहले, अगर मैं सही ढंग से याद है का उपयोग साइट पर विचरण से सख्ती से अधिक शक्तिशाली है declaration- साइट भिन्नता (हालांकि की लागत पर), या कम से कम जावा के वाइल्डकार्ड (हैं जो वास्तव में अधिक उपयोग-साइट भिन्नता से शक्तिशाली हैं)।

हालांकि, उत्तर यह नहीं बताता कि अंतर क्या है, केवल यही है।

संपादित करें: एक पहला अंतर मैं here (पृष्ठ 112 पर पहले पैराग्राफ) ने पाया है कि उपयोग साइट विचरण पूरी तरह से एक विधि गलत स्थिति में एक प्रकार पैरामीटर है कि जब वाइल्डकार्ड यह बुला की अनुमति बुला की अनुमति नहीं देता प्रतीत हो रहा है कुछ प्रकार के साथ। उदाहरण के लिए, आप पर add पर कॉल नहीं कर सकते हैं। जावा वाइल्डकार्ड, आप कर सकते हैं इस तरह के एक वर्ग पर कॉल add के साथ, लेकिन आप null argument.For contravariance के रूप में, एक कर सकते हैं कॉल किसी भी विधि का एक contravariant पैरामीटर देता है उपयोग करने के लिए है, लेकिन एक माना कि वापसी प्रकार Object है । लेकिन क्या यह एकमात्र अंतर है?

+0

क्या यह इस प्रश्न से अलग है? http://stackoverflow.com/questions/4231305/how-does-javas-use-site-variance-compare-to-cs-declaration-site-variance –

+1

@IsaiahvanderElst: नहीं, आपके द्वारा लिंक किया गया प्रश्न घोषणा साइट के बारे में है भिन्नता (उदाहरण के लिए, सी # ''''') बनाम साइट भिन्नता का उपयोग करें। मेरा सवाल उपयोग साइट भिन्नता बनाम वाइल्डकार्ड के बारे में है जो मेरे लिए बिल्कुल वही लगता है। लेकिन कम से कम आपके द्वारा लिखे गए प्रश्न में पहला जवाब मेरे दावे को बताता है: "या कम से कम जावा के वाइल्डकार्ड (जो वास्तव में उपयोग-साइट भिन्नता से अधिक शक्तिशाली हैं)" – gexicide

+0

@IsaiahvanderElst: मैंने अपनी पिछली टिप्पणी की पहली वाक्य गलत तरीके से phrased। मैं जो कहना चाहता था वह था "** हां **, यह प्रश्न आपके द्वारा लिंक किए गए एक से अलग है।" उम्मीद है कि स्पष्टीकरण में यह स्पष्ट हो गया है। – gexicide

उत्तर

5

इस विषय पर बहुत कुछ पढ़ने के बाद, मुझे लगता है कि this Altidor, Reichenbach, और Smaragdakis के पेपर में एक जवाब मिला है। जावा जेनरिक का उपयोग मुख्य साइट के विपरीत है जो साइट-वेरिएंस कैप्चर रूपांतरण है जो एक प्रकार पैरामीटर में पहले अज्ञात प्रकार के वाइल्डकार्ड को कैप्चर करने की अनुमति देता है। कागज से यह उदाहरण यह सबसे अच्छा बताते हैं:

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

<E> void swapLastTwo(Stack<E> stack) { 
     E elem1 = stack.pop(); 
     E elem2 = stack.pop(); 
     stack.push(elem2); 
     stack.push(elem1); 
    } 

हालांकि एक प्रोग्रामर swapLastTwo पद्धति के लिए एक मान तर्क के रूप प्रकार Stack<?> की एक वस्तु पारित करने के लिए चाहते हो सकता है, प्रकार पैरामीटर पारित करने के लिए E के लिए मैन्युअल विशिष्ट एड क्योंकि प्रकार ? से छिपा हुआ नहीं हो सकता है नहीं किया जा सकता प्रोग्रामर द्वारा नामित। हालांकि, Stack<?> टाइप करने से टाइप करें क्योंकि जावा संकलक को अज्ञात प्रकार (कैप्चर रूपांतरण) के लिए स्वचालित रूप से नाम उत्पन्न करने की अनुमति देता है और इस नाम का उपयोग आमंत्रण में करता है।

अर्थात, और जावा में, हम swapLastTwo() एक Stack<?> के रूप में इनपुट तर्क का उपयोग कर कॉल कर सकते हैं। कंपाइलर ? को प्रकार परिवर्तनीय E में कैप्चर करता है और इसलिए जानता है कि हम उन तत्वों पर push पर कॉल कर सकते हैं जिन्हें हम pop एड पर रखते हैं। उपयोग-साइट भिन्नता के साथ, हम ऐसा नहीं कर पाए क्योंकि टाइप सिस्टम pop से लौटा गया तत्व उस प्रकार की जानकारी खो देगा जो push अनुमानित है।

ध्यान दें कि हमें प्रकार को कैप्चर करने के लिए एक प्रकार पैरामीटर का उपयोग करना होगा। ऐसा नहीं करने से टाइपर चेकर pop से अलग प्रकार के प्रकार को push के प्रकार के रूप में अलग करेगा।

जैसे, इस जावा में संकलन नहीं करता है:

Stack<?> s = ...; 
s.push(s.pop()); 

यहाँ, s के तत्व के प्रकार दो अलग अलग ताजा प्रकार चर (capture 1 of ? और ग्रहण में capture 2 of ? बुलाया में लिया जाएगा प्रकार चेकर व्यवहार करता है। अलग और कोड संकलन नहीं करता है के रूप में इन प्रकार चर। एक सामान्य विधि का उपयोग करके हम किसी नामित पैरामीटर है कि अनुमति देता है push और pop बुला में ? के प्रकार पर कब्जा कर सकते हैं।

मुझे यकीन है कि नहीं कर रहा हूँ अगर यह onl है जावा वाइल्डकार्ड और "सामान्य" (जो कुछ भी है) के बीच वाई अंतर-साइट भिन्नता, लेकिन कम से कम यह एक बहुत ही उल्लेखनीय अंतर प्रतीत होता है।

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