Що означає "@private" в "Objective-C"?


Відповіді:


186

Це модифікатор видимості - це означає, що змінні екземплярів, оголошені як, @privateможуть бути доступні лише екземпляри одного класу . До приватних членів не можна отримати доступ до підкласів або інших класів.

Наприклад:

@interface MyClass : NSObject
{
    @private
    int someVar;  // Can only be accessed by instances of MyClass

    @public
    int aPublicVar;  // Can be accessed by any object
}
@end

Крім того, для уточнення, в Objective-C методи завжди є загальнодоступними. Однак існують способи "приховування" декларацій методів - для отримання додаткової інформації див. Це питання .


Що щодо змінних екземплярів, які знаходяться в дужках після @implementation? Вони завжди приватні?
Джон Генкель

Я знаю, що це старе ... Але це не модифікатор видимості. Це модифікатор доступу. Це більш важливе відмінність у C ++, але це також відмінність у Objective-C. Змінна видима компілятору. Компілятор просто не дозволяє вам отримати доступ до нього.
gnasher729

161

Як сказав htw, це модифікатор видимості. @privateозначає, що ivar (змінна інстанція) може бути доступна лише безпосередньо з екземпляра цього ж класу. Однак це для вас може не означати багато чого, тому дозвольте навести вам приклад. Ми будемо використовувати initметоди класів як приклади, для простоти. Я буду коментувати на черзі, щоб вказати на цікаві речі.

@interface MyFirstClass : NSObject
{
    @public
    int publicNumber;

    @protected  // Protected is the default
    char protectedLetter;

    @private
    BOOL privateBool;
}
@end

@implementation MyFirstClass
- (id)init {
    if (self = [super init]) {
        publicNumber = 3;
        protectedLetter = 'Q';
        privateBool = NO;
    }
    return self;
}
@end

@interface MySecondClass : MyFirstClass  // Note the inheritance
{
    @private
    double secondClassCitizen;
}
@end

@implementation MySecondClass
- (id)init {
    if (self = [super init]) {
        // We can access publicNumber because it's public;
        // ANYONE can access it.
        publicNumber = 5;

        // We can access protectedLetter because it's protected
        // and it is declared by a superclass; @protected variables
        // are available to subclasses.
        protectedLetter = 'z';

        // We can't access privateBool because it's private;
        // only methods of the class that declared privateBool
        // can use it
        privateBool = NO;  // COMPILER ERROR HERE

        // We can access secondClassCitizen directly because we 
        // declared it; even though it's private, we can get it.
        secondClassCitizen = 5.2;  
    }
    return self;
}

@interface SomeOtherClass : NSObject
{
    MySecondClass *other;
}
@end

@implementation SomeOtherClass
- (id)init {
    if (self = [super init]) {
        other = [[MySecondClass alloc] init];

        // Neither MyFirstClass nor MySecondClass provided any 
        // accessor methods, so if we're going to access any ivars
        // we'll have to do it directly, like this:
        other->publicNumber = 42;

        // If we try to use direct access on any other ivars,
        // the compiler won't let us
        other->protectedLetter = 'M';     // COMPILER ERROR HERE
        other->privateBool = YES;         // COMPILER ERROR HERE
        other->secondClassCitizen = 1.2;  // COMPILER ERROR HERE
    }
    return self;
}

Отже, щоб відповісти на ваше запитання, @private захищає ivars від доступу екземпляром будь-якого іншого класу. Зауважте, що два екземпляри MyFirstClass могли отримати доступ до всіх ivars один одного; передбачається, що оскільки програміст має повний контроль над цим класом, він розумно буде використовувати цю здатність.


20
Слід зазначити, що рідко використовувати @public, @proteced та @private в Objective-C. Кращим підходом є завжди використовувати аксесуари.
Георг Шоллі

1
@Georg, але як ви нав'язуєте використання аксесуарів, якщо ви не позначите своїх іварів обмеженою видимістю?
Грег Малетич

5
@Georg Schölly: Оскільки xcode 4.x + автоматично розміщує @privateв шаблоні для об'єкта, це вже не так рідко.
dawg

1
@Georg Я думаю, що @private, @protected може використовуватися для випадків, коли стосується спадкування, але не використовував його особисто :)
chunkyguy

5
Слід зазначити, що в наші дні є дуже мало підстав для розміщення змінних екземплярів у загальнодоступних заголовках. Їх можна розмістити безпосередньо на @implementationблоці. І коли ви це зробите, вони фактично є приватними незалежно від модифікаторів видимості, оскільки їх навіть не видно нікому поза цим файлом.
BJ Гомер

14

Важливо зрозуміти, що це означає, коли хтось каже, що ви не можете отримати доступ до @privateзмінної екземпляра. Справжня історія полягає в тому, що компілятор дасть вам помилку, якщо ви спробуєте отримати доступ до цих змінних у своєму вихідному коді. У попередніх версіях GCC та XCode ви отримаєте попередження замість помилки.

Так чи інакше, на час виконання всі ставки вимикаються. До них @privateі @protectedivars можна отримати доступ будь-якого класу. Ці модифікатори видимості просто ускладнюють складання вихідного коду до машинного коду, що порушує наміри модифікаторів видимості.

Не покладайтесь на модифікатори видимості ivar для безпеки! Їх взагалі немає. Вони призначені виключно для виконання бажань класного будівельника під час складання.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.