2009-05-10 11 views

Antwort

183

Es ist ein Sichtbarkeitsmodifizierer-es bedeutet, dass die Instanzvariablen deklariert als @private können nur von Instanzen derselben Klasse zugegriffen werden. Auf private Mitglieder kann nicht durch Unterklassen oder andere Klassen zugegriffen werden.

Zum Beispiel:

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

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

Auch zu klären, sind Methoden immer öffentlich in Objective-C. Es gibt jedoch Möglichkeiten, Methodendeklarationen zu "verbergen" - siehe this question für weitere Informationen.

+0

Was ist mit Instanzvariablen, die in der geschweiften Klammern nach der @ Implementierung sind? Sind sie immer privat? –

+0

Ich weiß, es ist alt ... Aber es ist kein Sichtbarkeitsmodifikator. Es ist ein Zugriffsmodifikator. Es ist eine wichtigere Unterscheidung in C++, aber es ist auch eine Unterscheidung in Objective-C. Die Variable ist für den Compiler sichtbar. Der Compiler lässt Sie einfach nicht darauf zugreifen. – gnasher729

160

Wie schon gesagt, es ist ein Sichtbarkeitsmodifikator. @private bedeutet, dass auf den ivar (Instanzvariable) nur direkt von einer Instanz derselben Klasse aus zugegriffen werden kann. Aber das mag Ihnen nicht viel bedeuten, also lassen Sie mich Ihnen ein Beispiel geben. Wir verwenden die Methoden der Klassen init der Einfachheit halber als Beispiele. Ich werde inline kommentieren, um auf interessante Dinge hinzuweisen.

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

So Ihre Frage zu beantworten, @private schützt ivars vor dem Zugriff durch eine Instanz einer anderen Klasse. Beachten Sie, dass zwei Instanzen von MyFirstClass direkt auf alle anderen Ivars zugreifen können. Es wird angenommen, dass, da der Programmierer die vollständige Kontrolle über diese Klasse direkt hat, er diese Fähigkeit mit Bedacht verwenden wird.

+19

Es sollte erwähnt werden, dass es ungewöhnlich ist, @public, @proteced und @private in Objective-C zu verwenden. Der bevorzugte Ansatz besteht darin, immer Accessoren zu verwenden. –

+0

BJ, dies ist die prägnanteste und hilfreichste Antwort auf diese Frage, die ich gesehen habe. Sehr gut gemacht. – MikeyWard

+1

@Georg, aber wie erzwingen Sie die Verwendung von Accessoren, es sei denn, Sie markieren Ihre Ivars mit eingeschränkter Sichtbarkeit? –

13

Es ist wichtig zu verstehen, was es bedeutet, wenn jemand sagt, dass Sie auf eine @private Instanzvariable nicht zugreifen können. Die wahre Geschichte ist, dass der Compiler Ihnen einen Fehler gibt, wenn Sie versuchen, auf diese Variablen in Ihrem Quellcode zuzugreifen. In früheren Versionen von GCC und XCode erhielten Sie nur eine Warnung anstelle eines Fehlers.

Wie auch immer, zur Laufzeit sind alle Wetten deaktiviert. Auf diese @private und @protected Ivars kann von einem Objekt jeder Klasse zugegriffen werden. Diese Sichtbarkeitsmodifikatoren machen es nur schwierig, den Quellcode in Maschinencode zu kompilieren, der die Absicht der Sichtbarkeitsmodifikatoren verletzt.

Verlassen Sie sich nicht auf ivar Sichtbarkeitsmodifikatoren für die Sicherheit! Sie bieten überhaupt keine. Sie dienen ausschließlich der Kompilierung der Wünsche des Klassenbauers.