जावा इंटरफेस और ऑब्जेक्टिव-सी प्रोटोकॉल के बीच अंतर?


93

मैं जावा जानता हूं, और अब मैं ऑब्जेक्टिव-सी सीख रहा हूं। वास्तव में जावा इंटरफेस और ऑब्जेक्टिव-सी प्रोटोकॉल के बीच अंतर क्या हैं?

जवाबों:


82

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

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

if ([myObject conformsToProtocol:@protocol(MyProtocol)]) {
    ...
}

नोट: Apple के दस्तावेजीकरण राज्य:

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

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

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

if ([myObject respondsToSelector:@selector(fillArray:withObject:)]) {
    [myObject fillArray:anArray withObject:foo];
    ...
}

यदि प्रतिबिंब का ओवरहेड एक समस्या बन जाता है, तो आप हमेशा पुन: उपयोग के लिए बूलियन परिणाम को कैश कर सकते हैं , लेकिन समय से पहले अनुकूलन करने का आग्रह करते हैं। :-)


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

3
"यदि कोई ऑब्जेक्टिव-सी क्लास एक औपचारिक प्रोटोकॉल में निहित तरीकों को लागू करता है, तो यह उस प्रोटोकॉल के लिए" अनुरूप "कहा जाता है, भले ही इसका इंटरफ़ेस स्पष्ट रूप से इसे न अपनाए। आप कोड में प्रोटोकॉल अनुरूपता का परीक्षण कर सकते हैं (-conformsToatrotocol का उपयोग करके: ) इस तरह "यह FALSE है। -conformsToProtocol:केवल तभी YES लौटाएगा यदि वर्ग स्पष्ट रूप से प्रोटोकॉल को अपनाता है। क्या आपने भी इसे आजमाया है?
user102008

2
आप सही हैं, -conformsToProtocol:वास्तव में यह आवश्यक है कि वर्ग (या पूर्वज) औपचारिक रूप से घोषणा करे कि वह प्रोटोकॉल को अपनाता है। निश्चित नहीं कि मुझे यह गलत कैसे मिला, सुधार के लिए धन्यवाद!
क्विन टेलर

18

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

जैसे

उद्देश्य सी:

@protocol MyProtocol
// Protocol definition
@end

id <MyProtocol> myProtocol;

 [myProtocol retain] // Compiler warning

जावा:

public interface MyInterface {
// interface definition
}

MyInterface myInterface;

myInterface.toString();  // Works fine.

उद्देश्य सी (निश्चित):

@protocol MyProtocol <NSObject>
// Protocol definition
@end

id <MyProtocol> myProtocol;

[myProtocol retain] // No Warning

25
ऐसा इसलिए है क्योंकि आईडी और NSObject समान नहीं हैं । जावा में, रूट ऑब्जेक्ट ऑब्जेक्ट है। ऑब्जेक्टिव-सी में, NSObject एक रूट वस्तु है, लेकिन नहीं है जड़ वस्तु। यदि आप सभी NSObject विधियों (क्लास विधियों के साथ-साथ प्रोटोकॉल) तक पहुंच चाहते हैं, तो यह स्पष्ट रूप से बताएं: NSObject <MyProtocol> myProtocol; इसके बजाय: आईडी <MyProtocol> ... जब आप आईडी का उपयोग कर रहे हैं तो आप कह रहे हैं: मुझे ऑब्जेक्ट की परवाह नहीं है, केवल प्रोटोकॉल है, जो आपके मामले में सच नहीं है।
जेसन कोको
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.