的指令@public,@protected和@private是 在Objective-C沒有約束力,他們是編譯器提示的變量約 可訪問性。 它不限制您訪問它們。
例如:
@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);
...
gcc編譯器吐出:
的main.m:56:1:警告:實例變量「y」爲@private;這將是未來的硬錯誤
Main.m:57:1:warning:實例變量'y'是@private;這將是一個嚴重的錯誤,將來
每進行一次「innapropriate」訪問「私有」成員y上,但是編譯也無妨。
在運行的時候你
x = 10 , y = -10
所以這真的是你不要寫訪問代碼這種方式,但由於objc是超的C, C語法工作得很好,所有的類是透明的。
您可以設置編譯器將這些警告視爲錯誤並保釋 - 但Objective-C不是在內部爲此類嚴格設置的。動態方法調度必須檢查每個調用的範圍和權限(slooooowwwww ...),因此,除編譯時警告外,系統期望程序員尊重數據成員範圍。
有幾個技巧來獲得objective-C中成員的隱私。 其中之一是確保將類的接口和實現分別放在單獨的.h和.m文件中,並將數據成員放在實現文件(.m文件)中。 然後,導入標頭的文件不能訪問數據成員,只能訪問類本身。 然後在標題中提供訪問方法(或不是)。如果需要,您可以在實現文件中實現setter/getter函數 以用於診斷目的,它們將被調用, ,但直接訪問數據成員將不會。
例如:
@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).
...
編譯器會發出這種明目張膽有心計的警告,但會繼續 和信任,你知道你在做什麼,你有你的理由(做(真的嗎?)您?)。 看起來像很多工作?容易出錯?耶嬰兒! 嘗試重構你的代碼,然後再訴諸如此類的魔術C技巧和肉丸手術。
但它確實存在。祝你好運。
具體而言,有問題的編譯器似乎是Clang> 2.(現有的)GCC不會這樣做。 – 2012-01-12 19:18:59
在這種情況下,'Clang'和'LLVM'是一樣的,對吧? – 2012-06-27 12:38:07
@ranReloaded - no。有gcc - gcc front&backend,gcc-llvm - gcc前端,llvm後端 - 和clang - clang前端,llvm後端。我只在叮噹時進行測試,Josh在其中一個gcc上測試過。 YMMV,只需使用你正在使用的任何編譯器就可以看到。 – CRD 2012-06-27 19:10:42