निर्देशों @public, @protected, और @private उद्देश्य-सी में बाध्यकारी नहीं हैं, वे संकलक के बारे में चर की पहुंच संकेत कर रहे हैं। यह आपको उन तक पहुंचने से प्रतिबंधित नहीं करता है।
उदाहरण:
@interface Example : Object
{
@public
int x;
@private
int y;
}
...
...
id ex = [[Example alloc ] init];
ex->x = 10;
ex->y = -10;
printf(" x = %d , y = %d \n", ex->x , ex->y);
...
जीसीसी संकलक बाहर थूक:
main.m: 56: 1: चेतावनी: उदाहरण चर 'y' @private है; भविष्य में यह एक कठिन त्रुटि होगी
मुख्य.एम: 57: 1: चेतावनी: आवृत्ति चर 'y' @private है; इस बार "निजी" सदस्य y करने के लिए प्रत्येक "innapropriate" एक्सेस का भविष्य
में एक कठिन त्रुटि हो, लेकिन यह वैसे भी संकलित करेंगे।
जब चलाने आप
x = 10 , y = -10
तो यह वास्तव में एक्सेस कोड इस तरह से लिखने के लिए नहीं आप पर निर्भर है, लेकिन क्योंकि ObjC एक सुपरसेट सी के है, सी वाक्य रचना बस ठीक काम करता है, और सभी मिल कक्षाएं पारदर्शी हैं।
आप इन चेतावनियों को त्रुटियों और जमानत के रूप में इलाज करने के लिए कंपाइलर सेट कर सकते हैं - लेकिन उद्देश्य-सी इस तरह की कठोरता के लिए आंतरिक रूप से स्थापित नहीं है। डायनामिक विधि प्रेषण को प्रत्येक कॉल (slooooowwwww ...) के लिए दायरे और अनुमति की जांच करनी होगी, इसलिए संकलन-समय चेतावनी से परे, सिस्टम प्रोग्रामर को डेटा सदस्य स्कोपिंग का सम्मान करने की अपेक्षा करता है।
उद्देश्य-सी में सदस्यों की गोपनीयता प्राप्त करने के लिए कई चालें हैं। एक यह सुनिश्चित करना है कि आप अपनी कक्षा के इंटरफ़ेस और कार्यान्वयन को क्रमशः अलग .h और .m फ़ाइलों में रखें, और डेटा सदस्यों को कार्यान्वयन फ़ाइल (.m फ़ाइल) में रखें। फिर हेडर आयात करने वाली फ़ाइलों के पास डेटा सदस्यों तक पहुंच नहीं है, केवल कक्षा ही। फिर शीर्षलेख में पहुंच विधियां (या) प्रदान करें। यदि आप चाहते हैं तो डायग्नोस्टिक उद्देश्यों के लिए कार्यान्वयन फ़ाइल में आपटर/गेटर फ़ंक्शंस लागू कर सकते हैं और वे कॉल करने योग्य, होंगे लेकिन डेटा सदस्यों तक सीधी पहुंच नहीं होगी।
उदाहरण:
@implementation Example2 :Object
{
//nothing here
}
double hidden_d; // hey now this isn't seen by other files.
id classdata; // neither is this.
-(id) classdata { return [classdata data]; } // public accessor
-(void) method2 { ... }
@end
// this is an "informal category" with no @interface section
// these methods are not "published" in the header but are valid for the class
@implementation Example2 (private)
-(void)set_hidden_d:(double)d { hidden_d = d; }
// You can only return by reference, not value, and the runtime sees (id) outside this file.
// You must cast to (double*) and de-reference it to use it outside of this file.
-(id) hidden_d_ptr { return &hidden_d;}
@end
...
[Main.m]
...
ex2 = [[Example2 alloc] init];
double d = ex2->hidden_d; // error: 'struct Example2’ has no member named ‘hidden_d’
id data = ex2->classdata; // error: 'struct Example2’ has no member named ‘classdata’
id data = [ex2 classdata] // OK
[ex2 set_hidden_d : 6.28318 ]; // warning:'Example2' may not respond to '-set_hidden_d:'
double* dp = [ex2 hidden_d_ptr]; // (SO UGLY) warning: initialization from incompatible pointer type
// use (double*)cast -- <pointer-to-pointer conversion>
double d = (*dp); // dereference pointer (also UGLY).
...
संकलक ऐसे ज़बरदस्त धोखाधड़ी के लिए चेतावनी जारी करेगा, लेकिन आगे जाना होगा और विश्वास आप जानते हैं कि आप क्या कर रहे हैं, और कि आप अपने कारणों (करते हैं (वास्तव में?) आप?)। बहुत सारे काम की तरह लगता है? प्रवण त्रुटि? हाँ बेबी! इस तरह जादू सी चाल और मीटबॉल सर्जरी का सहारा लेने से पहले अपने कोड को दोबारा करने का प्रयास करें।
लेकिन वहां है। सौभाग्य।
विशेष रूप से, प्रश्न में संकलक क्लैंग> 2. (मौजूदा) जीसीसी ऐसा नहीं करेगा। –
इस संदर्भ में, 'क्लैंग' 'एलएलवीएम' जैसा ही है, है ना? –
@ranReloaded - नहीं। जीसीसी-जीसीसी फ्रंट एंड बैकएंड, जीसीसी-एलएलवीएम - जीसीसी फ्रंटएंड, एलएलवीएम बैकएंड - और क्लैंग - क्लैंग फ्रंटएंड, एलएलवीएम बैकएंड है। मैंने केवल क्लैंग पर परीक्षण किया, जोश ने जीसीसी के एक परीक्षण पर परीक्षण किया। वाईएमएमवी, बस आप जिस भी कंपाइलर का उपयोग कर रहे हैं उसे देखें और देखें। – CRD