2009-05-10 13 views

risposta

183

E 'un modificatore visibilità -è significa che le variabili di istanza dichiarate come @private si può accedere solo da istanze della stessa classe. I membri privati ​​non sono accessibili per sottoclassi o altre classi.

Ad 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 pubbliche in Objective-C. Esistono modi per "nascondere" le dichiarazioni dei metodi, per ulteriori informazioni vedere this question.

+0

Che dire delle variabili di istanza incluse tra parentesi dopo l'implementazione @? Sono sempre privati? –

+0

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

160

Come diceva, è un modificatore di visibilità. @private significa che è possibile accedere a ivar (variabile di istanza) direttamente da un'istanza della stessa classe. Tuttavia, ciò potrebbe non significare molto per te, quindi lascia che ti dia un esempio. Useremo i metodi init delle classi come esempi, per ragioni di semplicità. Commenterò inline per indicare gli 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 Ivars da accesso da parte di un'istanza di una qualsiasi altra classe. Si noti che due istanze di MyFirstClass possono accedere direttamente a tutti gli altri ivars; si presume che dal momento che il programmatore ha il controllo completo su questa classe direttamente, utilizzerà saggiamente questa abilità.

+19

Va detto che è raro usare @public, @proteced e @private in Objective-C. L'approccio preferito è quello di utilizzare sempre gli accessor. –

+0

BJ, questa è la risposta più succinta e utile a questa domanda che ho visto. Molto bene. – MikeyWard

+1

@ Georg, ma come si fa a rinforzare l'uso degli accessor a meno che non si contrassegnino i tuoi ivar con visibilità limitata? –

13

È importante capire cosa significa quando qualcuno dice che non è possibile accedere a una variabile di istanza @private. La vera storia è che il compilatore ti darà un errore se tenti di accedere a queste variabili nel tuo codice sorgente. Nelle versioni precedenti di GCC e XCode, si otterrebbe solo un avvertimento invece di un errore.

In entrambi i casi, in fase di esecuzione, tutte le scommesse sono disattivate. Questi ivars @private e @protected sono accessibili da un oggetto di qualsiasi classe. Questi modificatori di visibilità rendono difficile compilare il codice sorgente in codice macchina che viola l'intento dei modificatori di visibilità.

Non fare affidamento sui modificatori di visibilità di ivar per motivi di sicurezza! Non forniscono affatto. Sono rigorosamente per l'applicazione in fase di compilazione dei desideri del costruttore della classe.