प्रारंभिक और देर से बाध्यकारी क्या है?


77

मैं जल्दी और देर से बंधने के बारे में सुनता रहता हूं, लेकिन मुझे समझ नहीं आता कि वे क्या हैं। मुझे निम्नलिखित स्पष्टीकरण मिला जो मुझे समझ में नहीं आता है:

अर्ली बाइंडिंग से डिज़ाइन समय के दौरान वैरिएबल के मानों को असाइन करने का उल्लेख होता है जबकि लेट बाइंडिंग से रन टाइम के दौरान वैरिएबल्स को वैल्यूज़ असाइन करने का उल्लेख होता है।

क्या कोई कृपया दो प्रकार के बंधन को परिभाषित कर सकता है और उनकी तुलना कर सकता है?


1
संकलित समय बनाम रनटाइम।
बार्लॉप

यहाँ इस विषय पर एक अच्छा पढ़ा है: en.wikibooks.org/wiki/Introduction_to_Programming_Languages/…
Jay Elston

जवाबों:


84

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

प्रकार

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

अक्सर [विशेष] गतिशील प्रकार, आत्मनिरीक्षण / प्रतिबिंब, झंडे और कंपाइलर विकल्पों का उपयोग करके या आभासी तरीकों के माध्यम से लागू किया जाता है और गतिशील प्रेषण को उधार लेकर और विस्तारित करके।

प्रारंभिक बंधन : प्रकार को रन-टाइम के दौरान चर का उपयोग करने से पहले जाना जाता है, आमतौर पर एक स्थिर, घोषणात्मक माध्यम से

मानक आदिम प्रकारों का उपयोग करके अक्सर लागू किया जाता है

कार्य

स्टेटिक डिस्पैच : संकलित समय पर ज्ञात, विशिष्ट कार्य या सबरूटीन; यह असंदिग्ध है और हस्ताक्षर से मेल खाता है

स्थिर कार्यों के रूप में लागू किया गया; किसी भी विधि में समान हस्ताक्षर नहीं हो सकते

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

में एकल [ गतिशील ] प्रेषण , केवल उदाहरण के प्रकार के उचित समारोह कार्यान्वयन निर्धारित करने के लिए प्रयोग किया जाता है। वैधानिक रूप से टाइप की जाने वाली भाषाओं में, इसका मतलब यह है कि उदाहरण प्रकार यह तय करता है कि किस तरह का प्रयोग किया जाता है, भले ही संदर्भित प्रकार का उपयोग किया जाता है, जब चर घोषित / असाइन किया गया हो। क्योंकि केवल एकल प्रकार - ऑब्जेक्ट इंस्टेंस का प्रकार - उपयुक्त कार्यान्वयन का अनुमान लगाने के लिए उपयोग किया जाता है, इस दृष्टिकोण को "एकल प्रेषण" कहा जाता है।

वहाँ भी है एक से अधिक [ गतिशील ] प्रेषण , जहां इनपुट पैरामीटर प्रकार भी इसका पता लगाने में जो समारोह कार्यान्वयन कॉल करने के लिए। क्योंकि कई प्रकार - दोनों प्रकार के उदाहरण और प्रकार (ओं) के पैरामीटर (ओं) को प्रभावित करते हैं कि किस पद्धति का चयन किया जाता है, इस दृष्टिकोण को "कई प्रेषण" कहा जाता है।

आभासी या सार कार्यों के रूप में लागू किया गया; अन्य सुरागों में ओवरराइड, छिपा हुआ या छायांकित तरीके शामिल हैं।

NB: ओवरलोडिंग में विधि शामिल है या नहीं, डायनेमिक प्रेषण भाषा-विशिष्ट है। उदाहरण के लिए, जावा में, ओवरलोड तरीके विधिपूर्वक भेजे जाते हैं।

मान

आलसी लोड हो रहा है : ऑब्जेक्ट आरंभीकरण रणनीति जो आवश्यकता तक मूल्य असाइनमेंट को धता बताती है ; किसी ऑब्जेक्ट को अनिवार्य रूप से मान्य लेकिन जानबूझकर अपूर्ण स्थिति में होने की अनुमति देता है और इसे लोड करने से पहले डेटा की आवश्यकता होने तक प्रतीक्षा करता है; अक्सर बड़े डेटासेट लोड करने या बाहरी संसाधनों पर प्रतीक्षा करने के लिए विशेष रूप से उपयोगी पाया जाता है

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

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

कंस्ट्रक्टर कॉल या इनिशियलाइज़ेशन के दौरान, जितनी जल्दी हो सके अपने सभी ज्ञात डेटा के साथ एक समग्र ऑब्जेक्ट प्रदान करके अक्सर लागू किया जाता है

डेटा बाइंडिंग : अक्सर दो संगत सूचना धाराओं के बीच एक सक्रिय लिंक या मानचित्र बनाना शामिल होता है ताकि एक में परिवर्तन दूसरे में वापस प्रतिबिंबित हो और इसके विपरीत; संगत होने के लिए उनके पास अक्सर एक सामान्य आधार प्रकार, या इंटरफ़ेस होना चाहिए

अक्सर क्लीनर प्रदान करने के प्रयास के रूप में लागू किया जाता है, विभिन्न अनुप्रयोगों के पहलुओं (जैसे देखने के लिए मॉडल, नियंत्रक के लिए मॉडल, आदि) और स्रोत और लक्ष्य, समापन बिंदु, बाँध / unbind, अद्यतन और घटनाओं जैसी अवधारणाओं के बारे में वार्ता के बीच लगातार सिंक्रनाइज़ेशन। on_bind, on_property_change, on_explicit, on_out_of_scope


संपादित करें नोट: अंतिम बार संपादित करें कि ये अक्सर कैसे होते हैं, उदाहरणों का विवरण प्रदान करने के लिए। विशेष कोड के उदाहरण पूरी तरह से कार्यान्वयन / रनटाइम / प्लेटफॉर्म पर निर्भर करते हैं


2
यह उत्तर वस्तु-उन्मुख भाषाओं के लिए भी विशिष्ट लगता है।
जैक

27

कंपाइलर द्वारा तय की गई किसी भी चीज को केवल / कंपाइल टाइम बाइंडिंग के लिए संदर्भित किया जा सकता है और RUNTIME पर जो भी निर्णय लिया जाना है उसे LATE / RUNTIME बाइंडिंग कहा जाता है ।

उदाहरण के लिए,

मेथड ओवरलोडिंग और मेथड ओवरराइडिंग

1) मेथड ओवरलोडिंग में आपके मेथड कॉल्स को मेथडलर द्वारा इस तरीके से तय किया जाता है कि जिसे फंक्शन कहा जाता है वह आपके कंपाइलर द्वारा कंपाइल टाइम पर तय किया जाता है। इसलिए पूरी तरह से बाध्यकारी है

2) मेथड ओवरराइडिंग में, RUNTIME पर यह तय किया जाता है कि किस विधि को कहा जा रहा है। इसलिए इसे LATE BINDING के रूप में दर्शाया गया है

इसे सरल और आसानी से प्राप्त करने की कोशिश की। उम्मीद है की यह मदद करेगा।


9

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

class A
{
public:
    void f() {}
    virtual void g() {}
};

class B : public A
{
    void f() {}
    virtual void g() {}
};

int main()
{
    A* a = new B;
    a->f();
    a->g();
}

इस उदाहरण में, a->f()वास्तव में कॉल करेगा void A::f(), क्योंकि यह प्रारंभिक (या सांख्यिकीय रूप से) बाध्य है, और इसलिए रनटाइम पर प्रोग्राम को लगता है कि यह केवल एक Aप्रकार के चर के लिए एक संकेतक है , जबकि a->g()वास्तव में कॉल करेगा void B::g(), क्योंकि संकलक, देखने g()में आभासी है, देखने के लिए कोड इंजेक्ट करता है रनटाइम पर कॉल करने के लिए सही फ़ंक्शन का पता।


1
"रनटाइम"? आप C ++ की बात कर रहे हैं। C ++ मशीन कोड के लिए सीधे संकलित करता है, इसे आभासी तरीकों को हल करने के लिए रनटाइम की आवश्यकता नहीं है।
तदमर्स

3
@tdammers C ++ वास्तव में रन टाइम लाइब्रेरी की आवश्यकता है, हालांकि वर्चुअल कॉल के लिए नहीं। यदि आप ध्यान से पढ़ते हैं, तो आप देखेंगे कि यह उत्तर कहता है कि संकलक " रनटाइम पर सही फ़ंक्शन [...] का पता देखने के लिए कोड इंजेक्ट करता है"।

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

@ मैं ने इस तरह के उत्तर से दूर रहने की कोशिश की, क्योंकि यह संकलक का कार्यान्वयन विवरण है, जो कुछ गूढ़ संकलक के लिए सच हो सकता है या नहीं भी हो सकता है। क्या मायने रखता है अवधारणा।
यम मार्कोविच

1
@tdammers और "रनटाइम" से मेरा मतलब है "रनटाइम पर प्रोग्राम"। जाहिर है C ++ प्रबंधित नहीं है। लेकिन जब से आपने मुझे दिखाया है तो यह भ्रम पैदा कर सकता है, मैं इसे पूर्ण शब्दों में बदल रहा हूं।
यम मारकोविच

5

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

  int add(int x,int y)
  {
    return x+y;
  }
  int sub(int x,int y)
  {
      return x-y;
  }


    int main()
    {
     //get user choice
     int(*fp)(int,int);
     //if add
      fp=add;
     //else if sub
     fp=sub;
     cout<<fp(2,2);
    }

यहाँ फ़ंक्शंस जोड़ और उप कार्य हैं (इसका पता संकलन समय-लिंकर पर बाँधा जाता है)

लेकिन फंक्शन पॉइंटर देर से बाइंड होता है fp कॉल या तो ऐड या सब को यूजर की पसंद के आधार पर [रनटाइम पर] कह सकता है।


3

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

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

माणिक में देर से बाध्यकारी प्रदर्शित करने के लिए एक उदाहरण:

a = 1 # a is an integer at this point
a.succ # asking for its successor is valid

class A
  def method_a
    # some code
  end
end

a = A.new
a.method_a # this is also valid
a.succ # this is not valid


class A # we can re-open the class and add a method
  def succ
    # some more code
  end
end
a.succ # now this is valid

क्रियाओं का उपरोक्त क्रम जावा जैसी भाषा में संभव नहीं है जहाँ सभी प्रकार के रन समय पर तय किए जाते हैं।


1

आपको एक अकादमिक परिभाषा देने के बजाय मैं आपको VBA का उपयोग करके वास्तविक दुनिया के उदाहरण का उपयोग करके कुछ अंतर दिखाने की कोशिश करूंगा:

प्रारंभिक बाध्यकारी:

Dim x As FileSystemObject
Set x = New FileSystemObject
Debug.Print x.GetSpecialFolder(0)

इसके लिए डिज़ाइन समय पर "Microsoft स्क्रिप्टिंग रनटाइम" घटक पर सेट होने के लिए एक संदर्भ की आवश्यकता होती है । इससे यह फायदा होता है कि आपको कंपाइल टाइम में पहले से ही एक एरर मैसेज मिल जाता है जब आपके पास टाइपो FileSystemObjectया मेथड जैसे नाम होते हैं GetSpecialFolder

देर से बाँधना

Dim x As Object
Set x = CreateObject("Scripting.FileSystemObject")
Debug.Print x.GetSpecialFolder(0)

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

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


-2

शायद देर से बाध्यकारी का सबसे आम उदाहरण इंटरनेट URL का समाधान है। यह गतिशील प्रणालियों और बड़ी प्रणालियों का समर्थन करता है, ताकि आप दुनिया में हर साइट को लिंक करने और बाँधने की कोशिश कर सकें, लेकिन इससे पहले कि आप पहुंच सकें, लेकिन दूसरी ओर यह रनवे पर कुछ ओवरहेड (डीएनएस लुकिंग, बहुत कम आईपी रूटिंग) को उकसाता है।

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

प्रत्येक प्रकार की लागत और लाभ हैं।


क्या आप बाध्यकारी की इस परिभाषा के लिए एक संदर्भ दे सकते हैं? मैंने इंटरनेट पते को "बाइंडिंग" के रूप में हल करने के बारे में नहीं सुना है, हालाँकि बाइंडिंग नामों को हल करने का कार्य है, मुझे लगता है कि किसी ने तर्क दिया है कि यूआरआई को इंटरनेट पते पर हल करने के लिए जल्दी / देर से बाध्यकारी की अवधारणा को लागू किया जा सकता है। लेकिन यह एक सामान्य व्याख्या नहीं है, और शुरुआती / देर से बाध्यकारी की अवधारणा उस समय से पहले होती है जहां कंप्यूटर आमतौर पर इंटरनेट से जुड़े थे।
जे एलस्टन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.