विस्तार विधि

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

हालाँकि, सभी भाषाएँ विस्तार विधियों को समान रूप से सुरक्षित तरीके से लागू नहीं करती हैं। उदाहरण के लिए, C#, जावा जैसी भाषाएं ( Manifold या Lombok द्वारा), और कोटलिन किसी भी तरह से विस्तारित वर्ग में परिवर्तन नहीं करते हैं, क्योंकि ऐसा करने से वर्ग पदानुक्रम टूट सकता है और आभासी विधि प्रेषण में बाधा उत्पन्न हो सकती है। यही कारण है कि ये भाषाएं विस्तार विधियों को सख्ती से वैधानिक रूप से लागू करती हैं और उन्हें आमंत्रित करने के लिए स्थिर प्रेषण का उपयोग करती हैं।

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

VB.NET और ऑक्सीजेन में, उन्हें " " कीवर्ड या विशेषता की उपस्थिति से पहचाना जाता है। Xojo में "Extends" कीवर्ड का उपयोग वैश्विक विधियों के साथ किया जाता है।

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

जावा में आप Manifold के माध्यम से विस्तार विधियाँ जोड़ते हैं, एक जार फ़ाइल जिसे आप अपने प्रोजेक्ट के क्लासपाथ में जोड़ते हैं। सी # के समान एक जावा एक्सटेंशन विधि को एक @Extension वर्ग में स्थिर घोषित किया जाता है, जहां पहले तर्क में विस्तारित वर्ग के समान प्रकार होता है और इसके साथ एनोटेट किया जाता है.

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

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

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

विस्तार विधियों को सक्षम करने वाली सुविधा के रूप में
एक्सटेंशन विधियों के आगे दूसरों द्वारा लिखे गए कोड को नीचे वर्णित अनुसार विस्तारित करने की अनुमति देने के बाद, एक्सटेंशन विधियां उन पैटर्नों को सक्षम करती हैं जो स्वयं के अधिकार में भी उपयोगी होती हैं। विस्तार विधियों को पेश करने का मुख्य कारण भाषा एकीकृत क्वेरी (LINQ) था। एक्सटेंशन विधियों के लिए कंपाइलर समर्थन पुराने कोड के साथ LINQ के गहरे एकीकरण की अनुमति देता है, साथ ही साथ C Sharp सिंटैक्स#क्वेरी सिंटैक्स के लिए समर्थन जो फिलहाल प्राथमिक Microsoft .NET भाषाओं के लिए अद्वितीय है।

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

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

निम्नलिखित कोड पर विचार करें और मान लें कि यह क्लास लाइब्रेरी में निहित एकमात्र कोड है। फिर भी, ILogger इंटरफ़ेस के प्रत्येक कार्यान्वयनकर्ता को MyCoolLogger कथन का उपयोग करके, इसे एक बार लागू किए बिना और ILogger के कार्यान्वयन प्रदान किए गए क्लास लाइब्रेरी को उप-वर्ग करने की आवश्यकता के बिना, एक स्वरूपित स्ट्रिंग लिखने की क्षमता प्राप्त होगी।


 * के रूप में उपयोग :

बेहतर ढीला युग्मन
विस्तार विधियाँ कक्षा पुस्तकालयों के उपयोगकर्ताओं को उस पुस्तकालय से आने वाले किसी प्रकार के तर्क, चर, या किसी अन्य चीज़ की घोषणा करने से परहेज करने की अनुमति देती हैं। कक्षा पुस्तकालय में उपयोग किए जाने वाले प्रकारों का निर्माण और रूपांतरण विस्तार विधियों के रूप में कार्यान्वित किया जा सकता है। रूपांतरणों और कारखानों को ध्यान से लागू करने के बाद, एक क्लास लाइब्रेरी से दूसरे में स्विच करना उतना ही आसान बनाया जा सकता है जितना कि यूज़िंग स्टेटमेंट को बदलना जो कंपाइलर को बाइंड करने के लिए विस्तार विधि उपलब्ध कराता है।

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

कोई यह तर्क दे सकता है कि विस्तार विधियों के बिना यह उतना ही संभव है, लेकिन कोई यह पाएगा कि व्यवहार में, विस्तार विधियां एक बेहतर अनुभव प्रदान करती हैं क्योंकि इसे काम करने के लिए वर्ग पदानुक्रम पर कम बाधाएं रखी जाती हैं - और वांछित के रूप में पढ़ा जाता है।

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

उत्पादकता
उदाहरण के लिए विचार करें IEnumerable और इसकी सादगी पर ध्यान दें - केवल एक विधि है, फिर भी यह LINQ का कम या ज्यादा आधार है. Microsoft .NET में इस इंटरफ़ेस के कई कार्यान्वयन हैं। फिर भी, जाहिर है, सिस्टम में परिभाषित तरीकों की पूरी श्रृंखला को लागू करने के लिए इनमें से प्रत्येक कार्यान्वयन की आवश्यकता बोझिल होगी। .Linq नामस्थान IEnumerables पर काम करने के लिए, भले ही Microsoft के पास सभी स्रोत कोड हों। इससे भी बदतर, इसके लिए Microsoft के अलावा सभी को उन सभी तरीकों को लागू करने के लिए IEnumerable का उपयोग करने पर विचार करने की आवश्यकता होगी, जो इस बहुत ही सामान्य इंटरफ़ेस के व्यापक उपयोग को देखते हुए बहुत ही विरोधी होते। इसके बजाय, इस इंटरफ़ेस की एक विधि को लागू करके, LINQ को तुरंत कम या ज्यादा इस्तेमाल किया जा सकता है। विशेष रूप से व्यावहारिक रूप से अधिकांश मामलों में देखने पर IEnumerable की GetEnumerator विधि को एक निजी संग्रह, सूची या सरणी के GetEnumerator कार्यान्वयन के लिए प्रत्यायोजित किया जाता है।

प्रदर्शन
उस ने कहा, प्रदर्शन को बेहतर बनाने के लिए, या अलग-अलग कार्यान्वित इंटरफ़ेस कार्यान्वयन से निपटने के लिए एक विस्तार विधि द्वारा प्रदान की गई सुविधा के अतिरिक्त कार्यान्वयन को जोड़ा जा सकता है, जैसे कि कंपाइलर को विशेष रूप से सरणियों के लिए IEnumerable का कार्यान्वयन प्रदान करना (System.SZArrayHelper में), जो कि यह स्वचालित रूप से सरणी टाइप किए गए संदर्भों पर एक्सटेंशन विधि कॉल के लिए चयन करेगा, क्योंकि उनका तर्क एक्सटेंशन विधि की तुलना में अधिक विशिष्ट होगा (यह टी [] मान) उसी नाम के साथ एक्सटेंशन विधि से जो IEnumerable इंटरफ़ेस (यह IEnumerable मान) के उदाहरणों पर संचालित होता है।

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

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

समस्या
प्रोग्रामिंग में, ऐसी परिस्थितियाँ उत्पन्न होती हैं जहाँ किसी मौजूदा वर्ग में कार्यक्षमता जोड़ना आवश्यक होता है - उदाहरण के लिए एक नई विधि जोड़कर। आम तौर पर प्रोग्रामर मौजूदा वर्ग के स्रोत कोड को संशोधित करेगा, लेकिन यह प्रोग्रामर को इन नए परिवर्तनों के साथ सभी निष्पादन योग्य को संकलित करने के लिए मजबूर करता है और इसके लिए आवश्यक है कि प्रोग्रामर वर्ग को संशोधित करने में सक्षम हो, जो हमेशा संभव नहीं होता है, उदाहरण के लिए तीसरे से कक्षाओं का उपयोग करते समय -पार्टी असेंबली (सीएलआई)। यह आम तौर पर तीन तरीकों में से एक में काम किया जाता है, जिनमें से सभी कुछ हद तक सीमित और अनजान हैं :
 * 1) क्लास को इनहेरिट करें और फिर व्युत्पन्न क्लास में इंस्टेंस मेथड में कार्यक्षमता को लागू करें।
 * 2) सहायक वर्ग में जोड़े गए स्थिर तरीकों में कार्यक्षमता को लागू करें।
 * 3) विरासत (कंप्यूटर विज्ञान) के बजाय वस्तु रचना # एकत्रीकरण का उपयोग करें।

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

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

वर्तमान VB.NET समाधान
अधिकांश तरीकों से, VB.NET समाधान उपरोक्त C# समाधान के समान है। हालाँकि VB.NET का एक अनूठा लाभ है कि यह सदस्यों को संदर्भ द्वारा विस्तार में पारित करने की अनुमति देता है (C# केवल मूल्य द्वारा अनुमति देता है)। निम्नलिखित के लिए अनुमति देना; क्योंकि विज़ुअल बेसिक स्रोत वस्तु को संदर्भ द्वारा पारित करने की अनुमति देता है, इसलिए किसी अन्य चर को बनाने की आवश्यकता के बिना सीधे स्रोत वस्तु में परिवर्तन करना संभव है। यह अधिक सहज भी है क्योंकि यह कक्षाओं के मौजूदा तरीकों के अनुरूप काम करता है।

विस्तार के तरीके
सी # 3.0 में विस्तार विधियों की नई भाषा सुविधा, हालांकि, बाद वाले कोड को संभव बनाती है। इस दृष्टिकोण के लिए निम्नानुसार एक स्थिर वर्ग और एक स्थिर विधि की आवश्यकता होती है।

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

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

स्थिर विधियों के साथ: विस्तार विधियों के साथ:

विस्तार विधियों और उदाहरण विधियों में नामकरण विरोध
सी # 3.0 में, एक वर्ग के लिए एक ही हस्ताक्षर के साथ एक उदाहरण विधि और एक विस्तार विधि दोनों मौजूद हो सकते हैं। ऐसे परिदृश्य में, उदाहरण विधि को विस्तार विधि से अधिक पसंद किया जाता है। नामकरण विरोध के बारे में न तो संकलक और न ही Microsoft Visual Studio IDE चेतावनी देता है। इस C# वर्ग पर विचार करें, जहाँ  इस वर्ग के उदाहरण पर विधि लागू की जाती है:

आवाहन करने का परिणाम  के उदाहरण पर   अगर केवल विस्तार विधि मौजूद है: एबीसी

परिणाम यदि उदाहरण विधि और विस्तार विधि दोनों मौजूद हैं: एबीसी

यह भी देखें

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

बाहरी संबंध

 * Open source collection of C# extension methods libraries. Now archived at Codeplex
 * Extension method in C#
 * Extension methods
 * C# Extension Methods. A collection.
 * extensionmethod.net Large database with C#, Visual Basic, F# and जावाscript extension methods
 * Explanation and code example
 * Defining your own functions in jQuery
 * Uniform function call syntax
 * Extension methods in C#
 * Extension Methods in जावा with Manifold
 * Extension Methods in जावा with Lombok
 * Extension functions in Kotlin