¿Qué significa "@private" en Objective-C?


Respuestas:


186

Es un modificador de visibilidad: significa que las variables de instancia declaradas como @privatesolo pueden acceder las instancias de la misma clase . No se puede acceder a los miembros privados mediante subclases u otras clases.

Por ejemplo:

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

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

Además, para aclarar, los métodos son siempre públicos en Objective-C. Sin embargo, hay formas de "ocultar" las declaraciones de métodos. Consulte esta pregunta para obtener más información.


¿Qué pasa con las variables de instancia que están entre llaves después de la @implementation? ¿Son siempre privados?
John Henckel

Sé que es viejo ... Pero no es un modificador de visibilidad. Es un modificador de acceso. Es una distinción más importante en C ++, pero también es una distinción en Objective-C. La variable es visible para el compilador. El compilador simplemente no te permite acceder a él.
gnasher729

161

Como dijo htw, es un modificador de visibilidad. @privatesignifica que solo se puede acceder al ivar (variable de instancia) directamente desde una instancia de esa misma clase. Sin embargo, eso puede no significar mucho para ti, así que déjame darte un ejemplo. Usaremos los initmétodos de las clases como ejemplos, por simplicidad. Voy a comentar en línea para señalar elementos de interés.

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

Entonces, para responder a su pregunta, @private protege a los ivars del acceso de una instancia de cualquier otra clase. Tenga en cuenta que dos instancias de MyFirstClass podrían acceder a todos los ivars de cada uno directamente; se supone que dado que el programador tiene control completo sobre esta clase directamente, usará esta habilidad sabiamente.


20
Cabe mencionar que es poco común usar @public, @proteced y @private en Objective-C. El enfoque preferido es usar siempre accesores.
Georg Schölly

1
@Georg, pero ¿cómo impones el uso de accesores a menos que marques tus ivars con visibilidad restringida?
Greg Maletic el

55
@Georg Schölly: dado que xcode 4.x + coloca automáticamente @privatela plantilla para un objeto, ya no es tan raro.
dawg

1
@Georg Creo @private, @protected se puede utilizar para los casos en los que interviene la herencia, no he utilizado personalmente aunque :)
chunkyguy

55
Cabe señalar que en estos días, hay muy pocas razones para poner variables de instancia en el encabezado público. Se pueden colocar directamente en el @implementationbloque. Y una vez que haces eso, son efectivamente privados sin importar los modificadores de visibilidad, ya que ni siquiera son visibles para nadie fuera de ese archivo.
BJ Homer

14

Es importante comprender lo que significa cuando alguien dice que no puede acceder a una @privatevariable de instancia. La verdadera historia es que el compilador le dará un error si intenta acceder a estas variables en su código fuente. En versiones anteriores de GCC y XCode, solo recibiría una advertencia en lugar de un error.

De cualquier manera, en tiempo de ejecución, todas las apuestas están apagadas. Se puede acceder a estos @privatey a los @protectedivars mediante un objeto de cualquier clase. Estos modificadores de visibilidad solo dificultan la compilación del código fuente en el código de máquina que viola la intención de los modificadores de visibilidad.

¡No confíe en los modificadores de visibilidad de ivar por seguridad! No proporcionan ninguno en absoluto. Son estrictamente para la aplicación en tiempo de compilación de los deseos del creador de la clase.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.