2010-04-03 19 views
35

Soy nuevo en Objective-C, pero tengo curiosidad sobre algo que realmente no he visto abordado en ningún otro lado.Variable de clase definida en @implementation en lugar de @interface?

Podría alguien decirme cuál es la diferencia entre una variable privada que se declara en el bloque @interface frente a una variable que se declara dentro del bloque @implementation exterior de los métodos de la clase, es decir:

@interface Someclass : NSObject { 

NSString *forExample; 

} 

@end 

vs.

@implementation Someclass 

NSString *anotherExample; 

-(void)methodsAndSuch {} 

@end 

parece ambas variables (forExample, anotherExample) son igualmente accesibles a lo largo de la clase y no puedo encontrar realmente una diferencia en su comportamiento. ¿La segunda forma también se llama una variable de instancia?

Respuesta

25

Este último no define una variable de instancia. Más bien, está definiendo una variable global en el archivo .m. Dicha variable no es exclusiva ni parte de ninguna instancia de objeto.

Tales globales tienen sus usos (miembros estáticos de C++ aproximadamente equivalentes, por ejemplo, almacenar una instancia singleton), pero normalmente los definirías en la parte superior del archivo antes de la directiva @implementation.

+0

Esto es lo que sospechaba y su respuesta tiene mucho sentido, pero si Intento acceder a 'anotherExample' en cualquier otra clase (por incluyendo apropiadamente 'Someclass' en esas clases) el compilador me dice que esta variable no está declarada. ¿Lo que da? – bitcruncher

+3

@bitcruncher porque 'anotherExample' es solo global para el archivo .m en el que se declaró. Si quiere que esté disponible para otros archivos, tendrá que declarar 'extern NSString * anotherExample;' en el archivo .h, luego '# import' the .h donde sea que necesite el global. Esto apesta a un olor a código, aunque tiene casos de usos válidos. –

+4

no hay código real está oliendo :-) esto fue solo una pregunta exploratoria. – bitcruncher

4

Si se declara una variable dentro de la sección @implementation, en realidad estás creando una variable global, visible en todas partes (en cada método en su aplicación).

Las variables miembro solo se pueden declarar en la sección @interface. Solo son accesibles en la clase en sí.

21

¡Son muy diferentes! El que está en @implementation es una variable global no exclusiva de cada instancia. Imagine que hay accesadores para ambas variables, escritos de la manera obvia. A continuación se muestra la diferencia de comportamiento aquí:

Someclass* firstObject = [[Someclass alloc] init]; 
Someclass* secondObject = [[Someclass alloc] init]; 

//forExample is an instance variable, and is unique to each instance. 
[firstObject setForExample:@"One"]; 
[secondObject setForExample:@"Two"]; 
NSLog(@"%@",[firstObject forExample]); //Result: "One" 
NSLog(@"%@",[secondObject forExample]); //Result: "Two" 

//anotherExample is a global variable, and is NOT unique to each instance. 
[firstObject setAnotherExample:@"One"]; 
[secondObject setAnotherExample:@"Two"]; 
NSLog(@"%@",[firstObject anotherExample]); //Result: "Two" (!) 
NSLog(@"%@",[secondObject anotherExample]); //Result: "Two" 

//Both instances return "Two" because there is only ONE variable this time. 
//When secondObject set it, it replaced the value that firstObject set. 

Si usted está buscando para este tipo de comportamiento, que podría ser mejor usar una variable de clase, así:

static NSString* yetAnotherExample = nil; 

continuación, puede utilizar métodos de clase para interactuar con la variable, y es claramente específico de la clase (a diferencia de la instancia específica o global).

+0

¿Sería 'anotherExample' una variable global de todo el programa o una variable global de clase? En otras palabras es 'anotherExample' una variable global que existe _always_ o es un global que existe cuando' Someclass' se instancia? – bitcruncher

+1

Existe * siempre *. Podría declarar 'extern NSString * anotherExample' en otro archivo .m y usarlo nuevamente. Por favor no. Pero podrías. : P – andyvn22

+0

por favor, no creo que realmente código de esta manera. :-) solo intentaba entender por qué otros hacían esto (fatalidad para iphone, por ejemplo) – bitcruncher

0

Para que quede claro, nunca jamás declarar una IBOutlet como var mundial (en la aplicación) si usted lo está utilizando para nibs/xibs localizadas.

yo pasamos unos horas averiguar la razón por la salida se puede conectar sólo en uno de los nibs localizadas en cualquier momento dado.

Gracias por esta pregunta y por sus respuestas!

3

El bloque privada declarada dentro del bloque @implementation es algo peligroso, me parece, en comparación con otro concepto programación orientada a objetos, por ejemplo, Java. Parece una variable miembro pero estática.

El programador noveles puede engañarse fácilmente con él. Escribo un programa de prueba y sorprendido con el comportamiento.

@interface SomeClass : NSObject 
{ 
    NSString *forExample; 
} 

- (void) set:(NSString *)one another:(NSString *)another; 
- (void)print; 

@end 

Implementación:

#import "SomeClass.h" 

@implementation SomeClass 

NSString *anotherExample; 

- (void) set:(NSString *)one another:(NSString *)another 
{ 
    forExample = one; 
    anotherExample = another; 
} 

- (void)print{ 
    NSLog(@"One = %@, another = %@", forExample, anotherExample); 
} 

@end 

prueba:

- (void)testClass { 
    SomeClass * s1 = [SomeClass new]; 
    [s1 set:@"one one" another:@"one another"]; 
    SomeClass *s2 = [SomeClass new]; 
    [s2 set:@"two one" another:@"two another"]; 
    [s1 print]; 
    [s2 print]; 
} 

Y la salida es,

One = one one, another = two another 
One = two one, another = two another 
Cuestiones relacionadas