संदेशों और तरीकों के बीच अंतर?


13

ऑब्जेक्टिव सी में आपको अन्य ऑब्जेक्ट्स को संदेश भेजने की अवधारणा है, और, यह C # और Java जैसी भाषाओं में मेथड कॉलिंग के समान है।

लेकिन वास्तव में सूक्ष्म अंतर क्या हैं ? मुझे अपने कोड के बारे में सोचते समय मैसेजिंग के बारे में कैसे सोचना चाहिए?

नोट: यहाँ पृष्ठभूमि की थोड़ी सी बात है, मैं C # / Java डेवलपर हूं जो ऑब्जेक्टिव सी के बारे में कुछ अवधारणाओं को समझने की कोशिश कर रहा हूं।


2
चूंकि वे सभी अलग-अलग भाषाएं हैं, इसलिए अंतर सूक्ष्म नहीं हैं। वे अलग-अलग भाषाएं हैं। "मेरे कोड के बारे में सोचते समय"? क्या कोड है? जावा या C # के बारे में सोचते समय, आप संदेशों के बारे में नहीं सोचते हैं। आप तरीकों के बारे में सोचते हैं। क्या आप स्पष्ट कर सकते हैं कि असंबंधित अवधारणाओं वाली असंबद्ध भाषा में "सूक्ष्म" अंतर कैसे हो सकते हैं?
S.Lott

1
कृपया आप stackoverflow.com पर सवाल पूछें
अमीर रज़ाई

1
क्या यह सवाल वास्तव में स्टैकऑवरफ्लो पर होना चाहिए? यह प्रोग्रामिंग अवधारणाओं के बारे में एक सवाल है जो मुझे मिले कुछ कोड के बारे में समस्या नहीं है। शायद मैं गलत हूँ, मुझे पता नहीं है - सीमाएँ धुंधली हो रही हैं ...
विदर्भ

1
@ वीदर, प्रश्न व्यक्तिपरक नहीं है। आप एक पाठ्यपुस्तक परिभाषा की तलाश कर रहे हैं। प्रोग्रामर राय, अनुभव और व्यक्तिपरक प्रश्नों के लिए अधिक है।
स्टीफन फुरलानी

1
ठीक है - इस सवाल को StackOverflow में ले जाने के लिए मॉडरेटर को लाने का कोई तरीका है?
विदर्भ

जवाबों:


10

एक संदेश एक चयनकर्ता का नाम है, और उस चयनकर्ता के लिए पैरामीटर।

एक चयनकर्ता एक प्रतीक है।

एक विधि एक वर्ग में कोड का एक टुकड़ा है जिसे एक चयनकर्ता द्वारा पहचाना जाता है।

दूसरे शब्दों में, [foo bar: baz]कहते हैं " @selector(bar:)पैरामीटर के साथ बुलाया संदेश bazवस्तु पर fooभेजें। आप उस संदेश को कई अलग-अलग वस्तुओं में भेज सकते हैं।

इसके विपरीत, विधि bar: एक के लिए Fooकैसा लग सकता है

-(int)bar:(int)n {
  return n + 1;
}

लेकिन एक FooTwoतरह लग सकता है

-(int)bar:(int)n {
  return n + 2;
}

(मुझे आशा है कि मेरे पास वाक्यविन्यास अधिकार है; मैंने अंतिम बार ऑब्जेक्टिव-सी को छुआ है।)

जब आप संदेश भेजते हैं, तो Objective-C कर्नेल उस संदेश को भेजता है fooजो यह तय करता है कि क्या वह संदेश को समझता है। यह इस आधार पर तय करता है कि वह उस चयनकर्ता द्वारा पहचानी गई विधि खोज सकता है या नहीं।

एक ही नाम के दो तरीके, और एक संदेश।

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


इसलिए ... एक संदेश तब होता है जब आप एक डिस्पेरफेस (a.invoke selector, args) और एक विधि कहते हैं जब आप एक इंटरफ़ेस (a.methodName) कहते हैं? क्या ऐसा नहीं होगा कि जावा, जावास्क्रिप्ट, सभी गतिशील भाषाओं में संदेश हैं क्योंकि सब कुछ सीधे इंटरफ़ेस के बजाय दोहरी इंटरफ़ेस के माध्यम से होता है और अस्थिर कूदता है)?
दिमित्री

4

विशुद्ध रूप से सैद्धांतिक दृष्टिकोण से, दोनों में कोई अंतर नहीं है - कई औपचारिक प्रमाण हैं जो दिखाते हैं कि दोनों पूरी तरह से बराबर हैं, और या तो पूरी तरह से दूसरे के संदर्भ में लागू किया जा सकता है।

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

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


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

@FrankShearar: क्षमा करें, लेकिन नहीं। मेरे द्वारा देखे गए सबूत मुद्रित किए गए थे, और बहुत पहले जब ओओपी और इसे लागू करने के तरीके पर्याप्त नए थे कि इस तरह की चीजों के बारे में सबूत शिक्षाविदों के लिए दिलचस्प थे।
जेरी कॉफिन

1

ऑब्जेक्टिव-सी में, संदेश लेट-बाउंड होते हैं। यही कारण है कि वे क्रम में हल कर रहे हैं। C # डायनामिक कीवर्ड के माध्यम से इसी तरह के निर्माण का समर्थन करता है जो किसी वस्तु को देर से बाउंड होने के रूप में घोषित करता है।


0

आमतौर पर मेथड कॉल्स का संकलन समय पर किया जाता है (जब तक कि आप जावा में प्रतिबिंब का उपयोग नहीं करते हैं), जबकि ऑब्जेक्टिव सी में संदेश रन टाइम पर भेजे जाते हैं।


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

2
हाँ। लेकिन फिर भी आप केवल कुछ (जावा में) के खिलाफ एक विधि कॉल को कोड कर सकते हैं जो संकलन समय पर अच्छी तरह से जाना जाता है। यदि MyObject या MyInterface में कोई विधि फू () परिभाषित नहीं है, तो MyObject.foo () को कॉल करना एक त्रुटि देगा। ObjC आपको MyObject पर एक संदेश 'foo' भेजने की अनुमति देगा - और यदि MyObject के पास कोई 'foo' नहीं है, तो यह रन टाइम पर बम होगा।
Heiko Rupp

मुझे लगा कि ऑब्जेक्टिव सी एक संकलित भाषा थी?
विदर्भ

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

@ विडार: यह संकलित बनाम व्याख्या का मुद्दा नहीं है, बल्कि स्थिर बनाम गतिशील है। जावा की तरह स्थिर ओओपी भाषाओं में, कंपाइलर यह सुनिश्चित करने के लिए जांच करता है कि संकलन चरण के दौरान एक वर्ग एक विधि को परिभाषित करता है। ऑब्जेक्टिव-सी जैसी डायनामिक-टाइप की गई भाषा में, संदेश रनटाइम पर पास किए जाते हैं।
मियादी

-1

संदेश या तो कर्नेल द्वारा या भाषा द्वारा स्वयं संभाला जाता है (उदाहरण के लिए ओबजैक के लिए, एक बहुत छोटा असेंबली कोड है जो करता है)।

उदाहरण के लिए लिनक्स कर्नेल में, संदेश सिस्टम कॉल / फ़ंक्शन के साथ किए जाते हैं: यदि आप यूनिक्स सिस्टम प्रोग्रामिंग के बारे में खोज करते हैं, तो आप उनके बारे में पा सकते हैं।

विधि कॉल और संदेश के बीच मुख्य अंतर यह है:

  • एक विधि कॉल केवल आपके कोड में होती है: ASM में इसका अनुवाद पारित तर्कों के PUSH द्वारा किया जाता है।

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


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