2010-03-30 7 views
5

Ho capito che in Objective-C devo dichiarare variabili di istanza come parte dell'interfaccia della mia classe anche se queste variabili sono dettagli di implementazione e hanno accesso privato.Objective-C: come prevenire le perdite di astrazione

In C "soggettiva", posso dichiarare una variabile nel mio file .c e non è visibile al di fuori di tale unità di compilazione. Posso dichiararlo nel corrispondente file .h, e quindi chiunque colleghi a quell'unità di compilazione può vedere la variabile.

Mi chiedo se ci sia una scelta equivalente in Objective-C, o se devo dichiarare ogni ivar in .h per la mia classe.

Ari.

+3

+1 e per la nota C soggettiva. –

risposta

2

Ari,

un buon riferimento per come realizzare esempio dichiarazioni di variabili "invisibili" può be found here con credito rispettosamente dato a Matt Gallagher.

Speranza che aiuta, Frank

+0

Giusto. Il bit che in realtà risponde alla mia domanda è che posso inserire parte dell'interfaccia @ nel mio file .m. Grazie per il puntatore. – iter

0

Per limitare l'accesso, è possibile utilizzare i @private o @protected parole chiave:

@interface Foo : NSObject { 
    @private 
    int barPrivate; 

    @protected 
    int barProtected; 

    @public 
    int barPublic; 
} 
@end 

EDIT:Scratch tutto, risulta ho davvero bisogno di dormire un po '.

+0

Esatto, non è possibile aggiungere variabili di istanza con una categoria. – codewarrior

+0

Sì, l'ho ricordato subito dopo aver postato la risposta. –

+0

Crea più di una istanza con valori diversi per 'bar' e vedrai -' bar' è una variabile globale. – Chuck

2

sono stati tradizionalmente necessario Le variabili di istanza per determinare la dimensione della classe. È sempre stata una cattiva pratica accedere direttamente agli ivar, e non è questo il punto. Nel runtime moderno, questo è meno necessario, ma in ogni caso non si tratta di una perdita di astrazione a meno che i client non facciano affidamento sugli ivars della classe, il che dovrebbe essere impossibile dal momento che li stai dichiarando come @protected o @private, giusto?

+0

Grazie per aver sottolineato l'intenzione positiva originale di enumerare esplicitamente gli ivar. Ho usato linguaggi veramente dinamici (Python, Lisp) per così tanto tempo, dimentico che alcune lingue vogliono conoscere le dimensioni al momento della compilazione. In molti modi l'apprendimento di Objective-C è come un viaggio nel passato. O giù per una miniera: riesco a vedere tutti i diversi strati di sedimenti che si accumulano nella lingua nel corso della sua vita. – iter

+0

@iter: Il bisogno non è più nemmeno lì in Objective-C. Il runtime moderno funziona in modo molto simile a quello di Python, dove le variabili di istanza possono essere assegnate tutte a willy-nilly senza essere dichiarate in un'intestazione, ma il linguaggio continua a muoversi attorno alla sintassi del suo passato. – Chuck

+0

Penso che potrei essermi imbattuto in questo l'altro giorno, però, quando ho iniziato a imbattersi in errori intermittenti objc_msgSend_fixup. Non sono sicuro al 100%, ma il problema è scomparso quando ho rimosso il object_setClass che ho usato per trasmettere un oggetto a una classe personalizzata con proprietà aggiunte. –

0

ivars sono @protected di default (anche se @private e @protected non garantiscono che le altre classi non possono accedervi - è sempre possibile accedere ivars con getValue:forKey:). Non si dovrebbe mai accedere direttamente ad ivars da altre classi direttamente - la "scelta" è se esporre o meno gli ivars come proprietà (basterà fare affidamento su tutte le classi che seguono la convenzione per non accedere direttamente a ivars).

Nel nuovo runtime obiettivo-c, non è necessario dichiarare affatto ivars, poiché possono essere sintetizzati in fase di esecuzione, ma sfortunatamente ciò non funziona con il simulatore iPhone, quindi per ora è meglio solo dichiarare tutti gli ivars nel file .h.

+0

Mi preoccupo meno di impedire al codice client di fare qualcosa di strano con il mio codice e altro ancora di dire al programmatore del client più sulla mia implementazione di quanto lui voglia sapere. Quando leggo un file .h, voglio imparare la forma "esterna" della libreria che sto usando. Se voglio conoscere il suo funzionamento interno, leggo il file .c o .m, a seconda dei casi. Mi piace mantenere questi due distinti e separati. – iter

+1

Sono d'accordo: è fastidioso che gli ivars siano nel file .h, ma come detto sopra, penso che sia a beneficio del compilatore. – shosti