विस्तार विधि

From alpha
Jump to navigation Jump to search

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

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

क्रमादेशन भाषाओं में समर्थन

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

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

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

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

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

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

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


विस्तार विधियों को सक्षम करने वाली सुविधा के रूप में

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

Console.WriteLine(new[] { Math.PI, Math.E }.Where(d => d > 3).Select(d => Math.Sin(d / 2)).Sum());
// Output:
// 1


सामान्य व्यवहार को केंद्रीकृत करें

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

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

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

namespace MyCoolLogger;

public interface ILogger
{
    void Write(string text);
}

public static class LoggerExtensions
{
    public static void Write(this ILogger logger, string format, params object[] args)
    {
        if (logger != null)
            logger.Write(string.Format(format, args));
    }
}
  • के रूप में उपयोग :
    var logger = new MyLoggerImplementation();
    logger.Write("{0}: {1}", "kiddo sais", "Mam mam mam mam ...");
    logger.Write("{0}: {1}", "kiddo sais", "Ma ma ma ma... ");
    logger.Write("{0}: {1}", "kiddo sais", "Mama mama mama mama ");
    logger.Write("{0}: {1}", "kiddo sais", "Mamma mamma mamma ... ");
    logger.Write("{0}: {1}", "kiddo sais", "Elisabeth Lizzy Liz...");
    logger.Write("{0}: {1}", "mamma sais", "WHAT?!?!!!");
    logger.Write("{0}: {1}", "kiddo sais", "hi.");
    


बेहतर ढीला युग्मन

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

धाराप्रवाह अनुप्रयोग क्रमादेशक के अंतरापृष्ठ

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

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

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

public class TodoItemContext : DbContext 
{
    public DbSet<TodoItem> TodoItems { get; set; }
    public DbSet<TodoList> TodoLists { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<TodoList>()
                    .HasKey(e => e.TodoListId)
                    .HasEntitySetName("Lists")
                    .HasMany(e => e.Todos)
                    .WithRequired(e => e.TodoList);
    }
}


उत्पादकता

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

public class BankAccount : IEnumerable<decimal> 
{
    private List<Tuple<DateTime, decimal>> credits; // assumed all negative
    private List<Tuple<DateTime, decimal>> debits; // assumed all positive

    public IEnumerator<decimal> GetEnumerator() 
    {
        var query = from dc in debits.Union(credits) 
                    orderby dc.Item1 /* Date */ 
                    select dc.Item2; /* Amount */
    
        foreach (var amount in query)
            yield return amount;
    }
}
// given an instance of BankAccount called ba and a using System.Linq on top of the current file,
// one could now write ba.Sum() to get the account balance, ba.Reverse() to see most recent transactions first,
// ba.Average() to get the average amount per transaction, etcetera - without ever writing down an arithmetic operator


प्रदर्शन

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

एक सामान्य आधार वर्ग की आवश्यकता को कम करना

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

रूढ़िवादी उपयोग

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

समस्या

प्रोग्रामिंग में, ऐसी परिस्थितियाँ उत्पन्न होती हैं जहाँ किसी सम्मलिता वर्ग में कार्यक्षमता जोड़ना आवश्यक होता है - उदाहरण के लिए एक नई विधि जोड़कर, सामान्यत: क्रमादेशित्र सम्मलिता वर्ग के स्रोत कूट को संशोधित करेगा, लेकिन यह क्रमादेशित्र को इन नए परिवर्तनों के साथ सभी निष्पादन योग्य को संकलित करने के लिए मजबूर करता है और इसके लिए आवश्यक है कि क्रमादेशित्र वर्ग को संशोधित करने में सक्षम हो, जो हमेशा संभव नहीं होता है, उदाहरण के लिए तीसरे से क्लास का उपयोग करते समय -पार्टी कोड़ांतरण (सीएलआई)। यह सामान्यत: तीन तरीकों में से एक में काम किया जाता है, जिनमें से सभी कुछ हद तक सीमित और अनजान हैं[citation needed]:

  1. क्लास को इनहेरिट करें और फिर व्युत्पन्न क्लास में उदाहरण विधि में कार्यक्षमता को लागू करें।
  2. सहायक वर्ग में जोड़े गए स्थिर तरीकों में कार्यक्षमता को लागू करें।
  3. विरासत (अभिकलित्र विज्ञान) के अतिरिक्त वस्तु रचना # एकत्रीकरण का उपयोग करें।

वर्तमान C # समाधान

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

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

string x = "some string value";
string y = Utility.Reverse(x);

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

string x = "some string value";
string y = x.Reverse();


वर्तमान VB.NET समाधान

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

Dim x As String = "some string value"
x.Reverse()

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

विस्तार के तरीके

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

public static class Utility
{
    public static string Reverse(this string input)
    {
        char[] chars = input.ToCharArray();
        Array.Reverse(chars);
        return new String(chars);
    }
}

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

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

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

HelperClass.Operation2(HelperClass.Operation1(x, arg1), arg2)

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

x.Operation1(arg1).Operation2(arg2)


विस्तार विधियों और उदाहरण विधियों में नामकरण विरोध

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

class AlphabetMaker 
{
    public void GetAlphabet()       
    {                               //When this method is implemented,
        Console.WriteLine("abc");   //it will shadow the implementation
    }                               //in the ExtensionMethods class.
}

static class ExtensionMethods
{
    public static void GetAlphabet(this AlphabetMaker am)   
    {                               //This will only be called                       
        Console.WriteLine("ABC");   //if there is no instance
    }                               //method with the same signature.   
}

उत्क्रियण करने का परिणाम GetAlphabet() के उदाहरण पर AlphabetMaker यदि केवल विस्तार विधि सम्मलित है:

एबीसी

परिणाम यदि उदाहरण विधि और विस्तार विधि दोनों सम्मलित हैं:

एबीसी

यह भी देखें

संदर्भ

  1. "विस्तार के तरीके". Microsoft. Retrieved 2008-11-23.
  2. "Extensions — The Swift Programming Language (Swift 5.7)". docs.swift.org. Retrieved 2022-06-12.


बाहरी संबंध