Che cosa significa "@private" in Objective-C?


Risposte:


186

È un modificatore di visibilità: significa che le variabili di istanza dichiarate come @privatesono accessibili solo da istanze della stessa classe . Ai membri privati ​​non è possibile accedere da sottoclassi o altre classi.

Per esempio:

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

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

Inoltre, per chiarire, i metodi sono sempre pubblici in Objective-C. Ci sono modi di "nascondere" le dichiarazioni dei metodi, però: vedi questa domanda per maggiori informazioni.


Che dire delle variabili di istanza tra parentesi graffe dopo l'implementazione @? Sono sempre privati?
John Henckel,

So che è vecchio ... Ma non è un modificatore di visibilità. È un modificatore di accesso. È una distinzione più importante in C ++, ma anche in Objective-C. La variabile è visibile al compilatore. Il compilatore non ti consente di accedervi.
gnasher729,

161

Come ha detto htw, è un modificatore di visibilità. @privatesignifica che è possibile accedere a ivar (variabile di istanza) direttamente dall'interno di un'istanza di quella stessa classe. Tuttavia, ciò potrebbe non significare molto per te, quindi lascia che ti faccia un esempio. Useremo i initmetodi delle classi come esempi, per semplicità. Commenterò in linea per indicare elementi di interesse.

@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;
}

Quindi, per rispondere alla tua domanda, @private protegge gli ivar dall'accesso di un'istanza di qualsiasi altra classe. Si noti che due istanze di MyFirstClass potrebbero accedere direttamente a tutti gli altri Ivar; si presume che, poiché il programmatore ha il controllo completo completo su questa classe, utilizzerà saggiamente questa capacità.


20
Va detto che è raro usare @public, @proteced e @private in Objective-C. L'approccio preferito è utilizzare sempre gli accessori.
Georg Schölly,

1
@Georg, ma come imponi l'uso degli accessori a meno che non contrassegni i tuoi ivar con visibilità limitata?
Greg Maletic,

5
@Georg Schölly: Poiché xcode 4.x + inserisce automaticamente @privateil modello per un oggetto, non è più così raro.
dawg,

1
@Georg Penso che @private, @protected può essere utilizzato per i casi in cui è coinvolta l'eredità, ma non l'ho usata personalmente :)
grosso

5
Va notato che in questi giorni, ci sono pochissime ragioni per mettere le variabili di istanza nell'intestazione pubblica. Possono essere posizionati direttamente sul @implementationblocco. E una volta che lo fai, sono effettivamente privati, indipendentemente dai modificatori di visibilità, in quanto non sono nemmeno visibili a nessuno al di fuori di quel file.
BJ Homer,

14

È importante capire cosa significa quando qualcuno afferma che non è possibile accedere a una @privatevariabile di istanza. La vera storia è che il compilatore ti darà un errore se provi ad accedere a queste variabili nel tuo codice sorgente. Nelle versioni precedenti di GCC e XCode, avresti semplicemente ricevuto un avviso invece di un errore.

Ad ogni modo, in fase di esecuzione, tutte le scommesse sono disattivate. Questi @privatee gli @protectedivar sono accessibili da un oggetto di qualsiasi classe. Questi modificatori di visibilità rendono difficile la compilazione del codice sorgente in codice macchina che viola l'intento dei modificatori di visibilità.

Non fare affidamento sui modificatori di visibilità Ivar per la sicurezza! Non forniscono affatto. Sono rigorosamente per l'applicazione in fase di compilazione dei desideri del costruttore di classi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.