Директивы @public, @protected и @private не являются обязательными в target-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: предупреждение: переменная экземпляра 'y' равна @private;в будущем это будет серьезной ошибкой
один раз для каждого "несоответствующего" доступа к "частному" члену y, но все равно компилируется.
Когдазапустите, вы получите
x = 10 , y = -10
Так что на самом деле вы НЕ должны писать код доступа таким образом, но поскольку objc является надмножеством C, синтаксис C работает просто отлично, и всеклассы прозрачны.
Вы можете настроить компилятор так, чтобы эти предупреждения воспринимались как ошибки и залог, но цель C не установлена внутри для такой строгости.Диспетчеризация динамического метода должна была бы проверять область действия и разрешение для каждого вызова (slooooowwwww ...), поэтому помимо предупреждения во время компиляции система ожидает, что программист соблюдает область видимости элемента данных.
Существует несколькоТрюки, чтобы получить конфиденциальность членов в цель-C.Один из них - убедиться, что вы поместили интерфейс и реализации вашего класса в отдельные файлы .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).
...
Компилятор выдаст предупреждения для таких вопиющих махинаций, но продолжит и будет верить, что вы знаете, что делаете (на самом деле?), И что у вас естьпричины (ты?).Кажется, много работы?Ошибка склонна?Yay Детка!Попробуйте сначала выполнить рефакторинг своего кода, прежде чем прибегать к волшебным трюкам C и операции с фрикадельками, как это.
Но это так.Удачи.