एक उद्देश्य-सी विधि नाम के अंतिम भाग को एक तर्क क्यों लेना चाहिए (जब एक से अधिक भाग हो)?


90

ऑब्जेक्टिव-सी में, आप विधि नामों की घोषणा नहीं कर सकते हैं जहां अंतिम घटक एक तर्क नहीं लेता है। उदाहरण के लिए, निम्नलिखित अवैध है।

-(void)take:(id)theMoney andRun;
-(void)take:(id)yourMedicine andDontComplain;

ऑब्जेक्टिव-सी को इस तरह क्यों बनाया गया? क्या यह स्मॉलटाक की सिर्फ एक कलाकृति थी जिससे किसी को छुटकारा पाने की आवश्यकता नहीं थी?

यह सीमा स्मॉलटाक में समझ में आती है, क्योंकि स्मॉलटाक में मैसेज इनवोकेशन के आस-पास सीमांकक नहीं है, इसलिए अंतिम घटक को अंतिम तर्क के लिए एक असमान संदेश के रूप में व्याख्या किया जाएगा। उदाहरण के लिए, के BillyAndBobby take:'$100' andRunरूप में पार्स किया जाएगा BillyAndBobby take:('$100' andRun)। यह ऑब्जेक्टिव-सी में कोई फर्क नहीं पड़ता जहां स्क्वायर ब्रैकेट की आवश्यकता होती है।

पैरामीटर रहित चयनकर्ता घटकों का समर्थन करने से हमें उन सभी सामान्य तरीकों से ज्यादा फायदा नहीं होगा, जिस तरह से एक भाषा को मापा जाता है, क्योंकि विधि नाम एक प्रोग्रामर चुनता है (जैसे कि runWith:बजायtake:andRun) एक कार्यक्रम के कार्यात्मक शब्दार्थ को प्रभावित नहीं करता है, और न ही भाषा की अभिव्यक्ति। वास्तव में, पैरामीटर रहित घटकों वाला एक प्रोग्राम एक के बिना अल्फा के बराबर है। मैं इस तरह के जवाब में दिलचस्पी नहीं रखता हूं कि इस तरह की सुविधा आवश्यक नहीं है (जब तक कि ऑब्जेक्ट-सी-डिज़ाइनर्स के घोषित कारण नहीं थे, क्या ब्रैड कॉक्स या टॉम लव को जानने के लिए कोई होता है? क्या वे यहां हैं?) या यह कहें कैसे विधि नाम लिखने के लिए तो सुविधा की जरूरत नहीं है। प्राथमिक लाभ पठनीयता और लेखनीयता है (जो पठनीयता की तरह है, केवल ... आप जानते हैं), क्योंकि इसका मतलब है कि आप विधि के नाम लिख सकते हैं जो प्राकृतिक भाषा के वाक्यों से भी अधिक निकटता से मिलते जुलते हैं। की पसंद -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication(जो मैट गलाघेर "कोको विद लव" पर बताते हैं-(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed, इस प्रकार उपयुक्त संज्ञा के तुरंत बाद पैरामीटर रखना।

Apple के ऑब्जेक्टिव-सी रनटाइम (उदाहरण के लिए) इस तरह के चयनकर्ताओं को संभालने में पूरी तरह से सक्षम है, इसलिए कंपाइलर क्यों नहीं? क्यों न वे विधि नामों में भी उनका समर्थन करें?

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

@interface Potrzebie : NSObject
-(void)take:(id)thing;
@end

@implementation Potrzebie
+(void)initialize {
    SEL take_andRun = NSSelectorFromString(@"take:andRun");
    IMP take_ = class_getMethodImplementation(self, @selector(take:));
    if (take_) {
        if (NO == class_addMethod(self, take_andRun, take_, "@@:@")) {
            NSLog(@"Couldn't add selector '%@' to class %s.", 
                  NSStringFromSelector(take_andRun), 
                  class_getName(self));
        }
    } else {
        NSLog(@"Couldn't find method 'take:'.");
    }
}

-(void)take:(id)thing {
    NSLog(@"-take: (actually %@) %@",NSStringFromSelector(_cmd), thing);
}
@end

int main() {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    Potrzebie *axolotl=[[Potrzebie alloc] init];
    [axolotl take:@"paradichloroaminobenzaldehyde"];
    [axolotl performSelector:NSSelectorFromString(@"take:andRun") 
                  withObject:@"$100"];
    [axolotl release];

    [pool release];
    return 0;
}

1
बिना कारण बताए यह संभव नहीं है, लेकिन यह क्यों संभव होना चाहिए? Apple के तरीकों का नाम होगा "takeAndRun:" और "takeAndDontComplain:";)

या takeAndRunWith:(id)theMoneyऔर takeAndDon'tComplainAbout:(id)yourMedicine। व्याकरणिक रूप से अजीब, सुनिश्चित करने के लिए।
मैथ्यू फ्रेडरिक

13
यह पूछने के लिए धन्यवाद - यह एक बहुत ही दिलचस्प सवाल है। मैं आसपास पूछूंगा।
बीबीम

5
यह सामयिक मजबूर व्याकरणिक अजीबता है जो मुझे सुविधा चाहती है।
21

1
बड़ा सवाल है। एक तरफ के रूप में, संकलक को इस तरह नामित विधियों के साथ कोई समस्या नहीं है: - (void) :(id)theMoney;या - (void) :(id)obj1 :(id)obj2;। इसलिए चयनकर्ताओं के पास कुछ भी नहीं है लेकिन कॉलन ठीक हैं। ;-)
ओले बेगमैन

जवाबों:


111

यह ब्रैड कॉक्स है। मेरे मूल उत्तर ने प्रश्न को गलत समझा। मैंने माना कि वास्तव में फास्ट मैसेजिंग को ट्रिगर करने के लिए एक हार्डकोड एक्सटेंशन था, न कि एक प्रकार की सिंथैटिक चीनी। असली जवाब यह है कि स्मॉलटॉक ने इसका समर्थन नहीं किया, शायद इसलिए कि इसका पार्सर (ग्रहण) अस्पष्टता से निपट नहीं सका। यद्यपि OC का वर्ग कोष्ठक किसी भी अस्पष्टता को हटा देगा, लेकिन मैंने स्मॉलटाक के कीवर्ड संरचना से हटने के बारे में नहीं सोचा था।


धन्यवाद, ब्रैड। आपके उत्तर की मेरी व्याख्या समान थी; SmallTalk से प्रस्थान पर विचार नहीं किया गया था।
bbum

42

21 साल की प्रोग्रामिंग ऑब्जेक्टिव-सी और इस सवाल ने कभी मेरा मन नहीं पार किया। भाषा डिजाइन को देखते हुए, कंपाइलर सही है और रनटाइम फ़ंक्शन गलत हैं ()।

विधि के नामों के साथ परस्पर संबंधित तर्कों की धारणा का अर्थ हमेशा यह होता है कि, यदि कम से कम एक तर्क है, तो अंतिम तर्क हमेशा विधि आह्वान वाक्यविन्यास का अंतिम भाग होता है।

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

जहाँ तक वस्तुनिष्ठ-सी को इस तरह से डिज़ाइन किया गया था, मुझे इस उत्तर पर संदेह होगा कि भाषा के मूल डिज़ाइनर ने सिलेक्टेड सिंटैक्स को अंतिम तर्क से परे जाने की अनुमति देने पर विचार नहीं किया।

यह एक सबसे अच्छा अनुमान है। जब मैं अधिक पता लगाऊंगा, तो मैं उन्हें एक उत्तर दूंगा और अपना उत्तर अपडेट करूंगा।


मैंने ब्रैड कॉक्स से इस बारे में पूछा और वह विस्तार से जवाब देने में बहुत उदार थे (धन्यवाद, ब्रैड !!) !!

मैं उस समय C पर जितना संभव था स्मॉलटाकल की नकल करने और उतनी ही कुशलता से करने पर ध्यान केंद्रित कर रहा था। कोई भी अतिरिक्त चक्र साधारण संदेश-सेवा को तेजी से बनाने में चला गया। एक विशेष संदेश विकल्प का कोई विचार नहीं था ("वास्तव में?" [Bbum : मैंने 'doSomething: withSomething: reallyFast' उदाहरण के रूप में ) का उपयोग करके पूछा क्योंकि साधारण संदेश पहले से ही उतने ही तेज़ थे जितना वे हो सकते हैं। इसमें सी प्रोटो-मेसेंजर के असेंबलर आउटपुट का हाथ-ट्यूनिंग शामिल था, जो इस तरह की पोर्टेबिलिटी दुःस्वप्न था कि कुछ नहीं तो उन सभी को बाद में निकाल लिया गया था। मुझे याद है कि हाथ से हैक करने वाला मेसेंजर बहुत तेज था; दो फ़ंक्शन कॉल की लागत के बारे में; एक मेसेंजर लॉजिक में और बाकी एक बार मेथड लुकअप करने के लिए।
स्टीव नरॉफ और अन्य द्वारा स्मालटाक के शुद्ध गतिशील टाइपिंग के बाद स्टैटिक टाइपिंग एन्हांसमेंट को बाद में जोड़ा गया। उसमें मेरी केवल सीमित भागीदारी थी।

पढ़ें ब्रैड का जवाब!


सिंटेक्स बुगाबोस ने मुझे बहुत दिलचस्पी दी।
आउटिस

1
मुझे लगता है कि अगर आपके पास एक बृहदान्त्र के बिना विधि नाम का एक हिस्सा था, तो आपको एक समस्या है क्योंकि आपको यह सुनिश्चित नहीं हो सकता है कि यह विधि नाम का हिस्सा है या नहीं।
NSResponder

2
इसने मेरे दिमाग को पहली बार पार किया जब मैंने एक प्रतिनिधि के लिए एक प्रोटोकॉल तैयार किया जो कि उद्देश्य-सी के साथ शुरू होने के बाद 21 साल से बहुत कम था। सामान्य पैटर्न प्रतिनिधि पैरामीटर संदेश भेजने वाले ऑब्जेक्ट को पहले पैरामीटर के रूप में आपूर्ति करना है। उदा -myObjectWithDelegate: (id) foo wantsYouToDoSomethingWith: (id) bar। यदि आप प्रोटोकॉल में एक विधि है जो कोई अन्य मापदंडों की जरूरत है यह विधि के नाम में एक दुर्लभ विसंगति की ओर जाता है। एक उदाहरण के लिए NSTableViewDataSource देखें। एक विधि अन्य सभी के अच्छे स्वच्छ पैटर्न का पालन नहीं करती है।
जेरेमीपीपी

21

आपकी जानकारी के लिए, रनटाइम वास्तव में चयनकर्ताओं के बारे में परवाह नहीं करता है, कोई भी सी स्ट्रिंग वैध है, आप इस तरह का चयनकर्ता बना सकते हैं: "== + === + ---__- ¨¨¨¨ ¨ ^ :::::: "किसी भी तर्क के साथ रनटाइम इसे स्वीकार नहीं करेगा, कंपाइलर सिर्फ पार्स नहीं कर सकता है या नहीं। जब चयनकर्ताओं की बात आती है तो पूरी तरह से पवित्रता की जाँच नहीं होती है।


7
+ 1 मैंने सोचा कि आप यह सुझाव देने के लिए पूरी तरह से पागल थे, लेकिन आप सही हैं। आप में से जो लोग विश्वास नहीं करते हैं: pastie.org/1388361
डेव डेलांग

6

मुझे लगता है कि वे ऑब्जेक्टिव-सी में समर्थित नहीं हैं क्योंकि वे स्मॉलटाक में उपलब्ध नहीं थे। लेकिन आपके विचार से इसका एक अलग कारण है: इनकी आवश्यकता नहीं है। क्या आवश्यक है 0, 1, 2, 3, ... तर्कों के साथ तरीकों के लिए समर्थन है। प्रत्येक तर्क के लिए, उन्हें कॉल करने के लिए पहले से ही एक कार्य सिंटैक्स है। किसी भी अन्य वाक्यविन्यास को जोड़ने से सिर्फ अनावश्यक भ्रम पैदा होगा।

यदि आप बहु-शब्द पैरामीटर रहित चयनकर्ता चाहते हैं, तो एक एकल अतिरिक्त शब्द के साथ क्यों रुकें? एक तो यह पूछ सकता है

 [axolotl perform selector: Y with object: Y]

यह भी समर्थित हो जाता है (यानी कि एक चयनकर्ता शब्दों का एक क्रम है, कुछ बृहदान्त्र और एक पैरामीटर के साथ, और अन्य नहीं)। जबकि यह संभव होगा, मैं मानता हूं कि किसी ने भी इसे सार्थक नहीं माना।


1
मैंने "उन्हें जरूरत नहीं है" तर्क के बारे में सोचा था, लेकिन मुझे इसमें कोई दिलचस्पी नहीं थी। अद्यतन किया गया प्रश्न यह स्पष्ट करता है। मापदंडों का चयन न करने के लिए मनमाने ढंग से चयनकर्ता घटकों को लिखने की क्षमता कम प्रदान करती है, क्योंकि रिक्त स्थान और ऊँट के मामले के बीच का अंतर एक अंतिम, पैरामीटर रहित घटक और प्राकृतिक भाषा के बयान और पुनर्लेखन मापदंडों के बीच अंतर से कम है (दोनों जिनमें से किया जाना चाहिए) ObjC के साथ, जैसा कि यह है)।
आउटिस

इसके अलावा, मनमाने ढंग से पैरामीटर रहित घटकों की अनुमति देने से कीवर्ड टकराव की संभावना बढ़ जाती है और नाम रिज़ॉल्यूशन जटिल हो जाता है, विशेषकर जब C ++ और ObjC को मिलाते हैं ( andऔर orविशेष रूप से स्टंबिंग ब्लॉक्स होंगे)। यह बहुत कम होगा यदि केवल विधि नाम के अंतिम घटक को कोई पैरामीटर न होने दिया जाए, क्योंकि इसमें कई शब्दों का समावेश होगा।
आउटिस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.