2010-09-20 11 views
17

मैं इस तरह एक वर्ग है कहते हैं:क्या मुझे आंतरिक रूप से आवृत्ति चर का उपयोग करते समय गुण या प्रत्यक्ष संदर्भ का उपयोग करना चाहिए?

@interface MyAwesomeClass : NSObject 
{ 
@private 
    NSString *thing1; 
    NSString *thing2; 
} 
@property (retain) NSString *thing1; 
@property (retain) NSString *thing2; 
@end 

@implementation MyAwesomeClass 
@synthesize thing1, thing1; 
@end 

जब thing1 और thing2आंतरिक तक पहुँचने (यानी, MyAwesomeClass के कार्यान्वयन के अंदर), बेहतर, संपत्ति का उपयोग करने के लिए है या सिर्फ उदाहरण चर संदर्भ सीधे (ऐसे मामलों को मानते हुए जिसमें हम "कस्टम" एक्सेस या म्यूटेटर में कोई काम नहीं करते हैं, यानी, हम बस सेट करते हैं और चर प्राप्त करते हैं)। प्री-ऑब्जेक्टिव सी 2.0, हम आमतौर पर केवल इवरों तक पहुंच सकते हैं, लेकिन सामान्य कोडिंग शैली/सर्वोत्तम अभ्यास अब क्या है? और क्या यह सिफारिश बदलती है यदि एक आवृत्ति चर/संपत्ति निजी है और कक्षा के बाहर भी पहुंच योग्य नहीं है? क्या आप प्रत्येक इवर के लिए संपत्ति बना सकते हैं, भले ही वे निजी हों, या केवल सार्वजनिक-सामना वाले डेटा के लिए? क्या होगा यदि मेरा ऐप कुंजी-मूल्य कोडिंग सुविधाओं का उपयोग नहीं करता है (क्योंकि केवीसी केवल संपत्ति पहुंच के लिए आग लगती है)?

मुझे निम्न-स्तर के तकनीकी विवरणों से परे देखने में रुचि है। उदाहरण के लिए, यह देखते हुए (उप इष्टतम) कोड की तरह:

@interface MyAwesomeClass : NSObject 
{ 
    id myObj; 
} 
@proprety id myObj; 
@end 

@implementation MyAwesomeClass 
@synthesize myObj; 
@end 

मुझे पता है कि myObj = anotherObject कार्यात्मक self.myObj = anotherObj के समान है।

लेकिन गुणक केवल आपके लिए एक्सेसर्स और म्यूटेटर लिखने के लिए संकलक को निर्देश देने के लिए केवल फैंसी वाक्यविन्यास नहीं हैं; वे डेटा को बेहतर encapsulate करने का एक तरीका भी हैं, यानी, आप उन गुणों पर भरोसा रखने वाले वर्गों को फिर से लिखने के बिना कक्षा के आंतरिक कार्यान्वयन को बदल सकते हैं। मुझे जवाब में दिलचस्पी है जो कक्षा के अपने आंतरिक कोड से निपटने के दौरान इस encapsulation मुद्दे के महत्व को संबोधित करते हैं। इसके अलावा, उचित रूप से लिखित गुण केवीसी अधिसूचनाओं को आग लगा सकते हैं, लेकिन प्रत्यक्ष ivar पहुंच नहीं होगी; क्या इससे कोई फर्क नहीं पड़ता कि मेरा ऐप केवीसी फीचर्स का उपयोग नहीं कर रहा है अब, अगर भविष्य में हो सकता है?

उत्तर

8

मुझे नहीं लगता कि किसी भी तरह से 'बेहतर' है। आप दोनों शैलियों को आम उपयोग में देखते हैं, इसलिए अब भी एक सामान्य/सर्वोत्तम अभ्यास नहीं है। मेरे अनुभव में, इस्तेमाल की जाने वाली शैली पर बहुत कम प्रभाव पड़ता है कि मैं कुछ कार्यान्वयन फ़ाइल को कितनी अच्छी तरह से पचता हूं। अन्य लोगों के कोड को देखते समय आप निश्चित रूप से दोनों शैलियों (और बीच में) के साथ सहज रहना चाहते हैं।

रखरखाव के मामले में प्रत्येक आंतरिक इवर के लिए संपत्ति का उपयोग थोड़ा सा हो सकता है। मैंने इसे किया है, और इसमें एक गैर-मामूली काम जोड़ा गया है जो मुझे नहीं लगता कि मेरे लिए भुगतान किया गया है। लेकिन यदि आपके पास हर जगह self.var जैसे लगातार कोड देखने के लिए एक मजबूत इच्छा/ओसीडी है, और जब भी आप कक्षा देखते हैं तो आपके दिमाग के पीछे यह होता है, फिर इसका उपयोग करें। उत्पादकता पर एक नाराज लगने वाले प्रभाव को प्रभावित न करें।

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

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

मुझे पता चला है कि आंतरिक कार्यान्वयन से निपटने के दौरान, मुझे तुरंत एक अच्छा संभाल मिल जाता है कि प्रत्येक इवर को बिना किसी पहुंच के कैसे पहुंचाया जाना चाहिए।

  • पढ़ना ivars:, जब तक कि वहाँ एक कस्टम गेटर (जैसे आलसी निर्माण)
  • लेखन ivars है सीधी पहुँच: alloc/dealloc में सीधे

    आप रुचि रखते हैं, अपने खुद के दृष्टिकोण यह है। कहीं और, एक निजी संपत्ति के माध्यम से यदि कोई मौजूद है। thing1 KVO साथ प्रयोग किया जाता है

3

thing1 = something; और self.thing1 = something; का एक काम में फर्क सिर्फ इतना है कि यदि आप संपत्ति काम आपरेशन (retain, copy, आदि), सौंपा वस्तु पर किया करना चाहते हैं, तो आप एक संपत्ति उपयोग करने की आवश्यकता है। गुणों के बिना असाइन करना प्रभावी रूप से केवल प्रदान की गई वस्तु का संदर्भ निर्दिष्ट करेगा।

मुझे लगता है कि आंतरिक डेटा के लिए एक संपत्ति को परिभाषित करना अनावश्यक है। केवल इवर के लिए गुण परिभाषित करें जिन्हें अक्सर एक्सेस किया जाएगा और विशिष्ट म्यूटेटर व्यवहार की आवश्यकता होगी।

11

यदि आप कोको-देव मेलिंग सूची पर समय बिताते हैं, तो आप पाएंगे कि यह एक बहुत ही विवादास्पद विषय है।

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

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

ऐप्पल के नमूना कोड को देखते हुए यह पता चलता है कि वे इस विषय पर सभी जगह हैं। कुछ नमूने आंतरिक रूप से गुणों का उपयोग करते हैं, कुछ आइवर का उपयोग करते हैं।

मैं सामान्य रूप से कहूंगा कि यह स्वाद का विषय है और ऐसा करने का कोई सही तरीका नहीं है। मैं खुद दोनों शैलियों का मिश्रण का उपयोग करता हूं।

+0

धन्यवाद। आप और एलन डिंग दोनों के पास विशेष रूप से अच्छे जवाब थे। – mipadi

2

तो यह एक अच्छा विचार self.thing1= उपयोग करने के लिए जब आप इसे सेट है। यदि thing1@public है, तो यह मानना ​​सबसे अच्छा है कि किसी दिन किसी दिन कभी केवीओ के साथ इसका उपयोग करना चाहेगा।

हैं thing1 जटिल सेट अर्थ विज्ञान है कि आप हर जगह आप इसे सेट दोहराने के लिए नहीं करना चाहती है तो self.thing1= के माध्यम से (उदाहरण retain, या गैर nonatomic के लिए) एक अच्छा विचार है।

बेंच मार्किंग से पता चलता है कि फोन करने setThing1: महत्वपूर्ण समय लग रहा है तो आप self.thing1= के उपयोग के बिना यह स्थापित करने के लिए तरीके के बारे में सोचना चाहते हो सकता है, तो - शायद ध्यान दें कि यह KVO'ed नहीं किया जा सकता, या देख सकते हैं मैन्युअल रूप से लागू करने KVO बेहतर है (उदाहरण के लिए यदि आप इसे कहीं लूप में 3000 बार सेट करते हैं, तो आप इसे self->thing1 3000 बार के माध्यम से सेट करने में सक्षम हो सकते हैं, और बदलने के बारे में 2 केवीओ कॉल बदल सकते हैं और बदल रहे हैं)।

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

हालांकि जब मैं सीधे ivar एक्सेस के साथ चीजें सेट करता हूं तो मैं इसे केवल self->thing1= के माध्यम से करने की कोशिश करता हूं, जो उन्हें सभी को ढूंढने और उन्हें बदलने में बहुत आसान बनाता है अगर मुझे कभी भी केवीओ का उपयोग करने की आवश्यकता मिलती है, या इसे सार्वजनिक करने के लिए , या एक अधिक जटिल एक्सेसर बनाने के लिए।

0

यहां वर्णित अन्य चीजें ठीक हैं। कुछ चीजें जो अन्य उत्तरों को याद करती हैं वे हैं:

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

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

यह केवीओ मुद्दे से भी संबंधित है। Init में, कोई भी संभवतः आपको (वैध रूप से) देख नहीं सकता है, और dealloc में, किसी भी शेष पर्यवेक्षक के पास एक बेवकूफ बेकार (यानी bogus) संदर्भ है। वही तर्क गुणों की परमाणु गारंटी पर भी लागू होता है। (यानी इनट रिटर्न से पहले समवर्ती पहुंच कैसे होती है और डेलोक के दौरान होने वाली पहुंच स्वाभाविक रूप से त्रुटियां होती हैं।)

यदि आप सीधे और एक्सेसर/म्यूटेटर उपयोग को मिलाकर मेल खाते हैं, तो आप केवल केवीओ और परमाणुता से नहीं चलते हैं, लेकिन उपclassers भी।

संबंधित मुद्दे

 संबंधित मुद्दे