2010-04-03 16 views
35

Sono nuovo di Objective-C, ma sono curioso di qualcosa che non ho mai visto indirizzato da nessun'altra parte.Variabile di classe definita in @implementation anziché in @interface?

qualcuno potrebbe dirmi qual è la differenza tra una variabile privata che è dichiarato al @interface blocco rispetto a una variabile che viene dichiarata all'interno del blocco @implementation al di fuori dei metodi di classe, vale a dire:

@interface Someclass : NSObject { 

NSString *forExample; 

} 

@end 

vs.

@implementation Someclass 

NSString *anotherExample; 

-(void)methodsAndSuch {} 

@end 

Sembra entrambe le variabili (forExample, anotherExample) sono ugualmente accessibili per tutta la classe e non riesco davvero a trovare una differenza nel loro comportamento. Il secondo modulo è anche chiamato una variabile di istanza?

risposta

25

Quest'ultimo non sta definendo una variabile di istanza. Piuttosto, sta definendo una variabile globale nel file .m. Tale variabile non è univoca o parte di alcuna istanza di oggetto.

Tali globalmente hanno i loro usi (membri statici C++ approssimativamente equivalenti, ad esempio la memorizzazione di un'istanza singleton), ma normalmente le definireste nella parte superiore del file prima della direttiva @implementation.

+0

Questo è quello che sospettavo e la tua risposta ha perfettamente senso, ma se Provo ad accedere a 'anotherExample' in qualsiasi altra classe (da includendo correttamente 'Someclass' in quelle classi) il compilatore mi dice che questa variabile non è dichiarata. Cosa dà? – bitcruncher

+3

@bitcruncher perché 'anotherExample' è solo globale del file .m in cui è stato dichiarato. Se vuoi che sia disponibile per altri file, devi dichiarare 'extern NSString * anotherExample;' nel file .h, quindi '# import' il file .h ovunque ti serva il globale. Questo puzza di odore di codice, sebbene abbia casi di utilizzo validi. –

+4

nessun codice attuale puzza :-) questa era solo una domanda esplorativa. – bitcruncher

4

Se si dichiara una variabile all'interno della sezione @implementation, si sta effettivamente creando una variabile globale, visibile ovunque (in ogni metodo nell'applicazione).

variabili membro possono essere dichiarate solo nella sezione @interface. Sono accessibili solo nella classe stessa.

21

Sono molto diversi! Quello in @implementation è una variabile globale non unica per ogni istanza. Immagina che ci fossero degli accessor per entrambe le variabili, scritte in modo ovvio. Poi la differenza di comportamento è mostrato qui:

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. 

Se siete alla ricerca di questo tipo di comportamento, si potrebbe essere meglio utilizzare una variabile di classe, in questo modo:

static NSString* yetAnotherExample = nil; 

quindi è possibile utilizzare metodi di classe per interagire con la variabile, ed è chiaramente specifico per classe (al contrario di istanza specifica o globale).

+0

Quindi 'anotherExample' dovrebbe essere una variabile globale a livello di programma o una variabile globale di classe? In altre parole è 'anotherExample' una variabile globale che esiste _always_ o è un globale che esiste quando' Someclass' viene istanziato? – bitcruncher

+1

Esiste * sempre *. Puoi dichiarare 'extern NSString * anotherExample' in un altro file .m e usarlo di nuovo. Per favore non farlo. Ma tu potresti : P – andyvn22

+0

, per favore, non pensare che io in realtà codice in questo modo. :-) Sto solo cercando di capire perché altri stessero facendo questo (doom per iphone, per esempio) – bitcruncher

0

Giusto per essere chiari, mai mai mai dichiarare un IBOutlet come var globale (per l'attuazione), se lo si utilizza per pennini localizzati/xibs.

ho trascorso un paio d'ore per capire il motivo per cui l'uscita è collegabile solo in uno dei pennini localizzati in qualsiasi momento.

Grazie per questa domanda e le risposte!

3

Il blocco privato dichiarata all'interno del blocco @implementation è un po 'pericoloso, mi sembra, a confronto con altro concetto OOP esempio Giava. Sembra una variabile membro, ma piuttosto statica.

programmatore alle prime armi può facilmente ingannare con esso. Scrivo un programma di test e mi sorprendo del comportamento.

@interface SomeClass : NSObject 
{ 
    NSString *forExample; 
} 

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

@end 

Implementazione:

#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 

prova:

- (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]; 
} 

E l'uscita è,

One = one one, another = two another 
One = two one, another = two another 
Problemi correlati