2009-08-26 8 views

risposta

8

Se si sta solo accedendo a loro, non ci sono molti motivi per utilizzare self.member. Se stai facendo un compito, è meglio se stai facendo qualcosa di più del semplice parametro @property (assign) - per esempio, conserva, copia, ecc. In modo che possa salvare sul codice che stai scrivendo. Un esempio:

myObject = anotherObject; 
self.myObject = anotherObject; 

La seconda scelta farà in modo che si sta effettivamente assegnare l'oggetto nel modo desiderato (ottenere una copia, aumentando il numero di conservare, ecc). Non è diverso da [self setMyObject:anotherObject].

Poiché il dot-notation viene sostituito da un messaggio dal compilatore (analogamente a come x[5] diventa *(x + 5*sizeof(x)) nel normale funzionamento dell'array), non c'è overhead o extra efficienza nell'utilizzo di dot-notation sui normali messaggi.

1

Non si dovrebbe quasi mai chiamare gli accessor di proprietà dall'implementazione della stessa classe. I metodi di istanza della classe hanno un comodo accesso allo stato interno, quindi di solito ha senso accedere direttamente a quello stato.

Se si utilizzano accessori sintetizzati, chiamarli aggiunge solo (probabilmente) un sovraccarico non necessario. Se gli accessor hanno un'implementazione più complicata, stai solo oscurando lo scopo del codice.

Infine, alcune persone che sono nuove a Objective-C usano la sintassi self.property e gli accessors sintetizzati per cercare di evitare di dover capire la gestione della memoria del cacao. Hai davvero bisogno di imparare come funziona, quindi cercare di evitare di farlo è controproducente.

+0

Solo perché è possibile interferire con lo stato interno dell'oggetto tutto volente o nolente non significa che dovresti. E solo perché capisci come funziona la gestione della memoria non significa che lo farai alla perfezione in tutto il team. Duplicare la responsabilità della gestione della memoria tra una serie di metodi è la richiesta di bug. – Chuck

+0

Sono rispettosamente in disaccordo. Se le tue classi hanno molti accessors sintetizzati @, probabilmente sono mal progettati. Se hai implementato accessor non banali, allora vuoi stare attento a usarli in modo appropriato. Gli accessor di proprietà devono essere utilizzati per creare un'interfaccia * esterna * per la classe. a volte, ha senso per la classe utilizzare internamente l'interfaccia esterna, ma spesso non è necessario (o controproducente). –

+0

In ogni caso, se vuoi davvero usare gli accessors, usa il "self". la sintassi oscura solo ciò che sta accadendo, quindi dovresti comunque usare la messaggistica esplicita. Se stai impostando una proprietà, "[self setFoo: value]" ha solo 5 caratteri più lunghi di "self.foo = value". Per l'accesso in lettura, la differenza è ancora meno. Scriverai il codice solo una volta, quindi dovresti cercare di rendere più chiaro ciò che accade quando tu (o qualcun altro) lo leggi più tardi. –

1

Se si utilizza Core Data, è necessario utilizzare sempre gli accessors, poiché alcune proprietà potrebbero non essere caricate dall'archivio permanente finché non è necessario. (Supponendo che si sta utilizzando un negozio di SQLite, comunque.)

Se non si utilizza Core Data, sei generalmente sicuri di utilizzare solo myObject direttamente se sei solo la lettura il valore. Se stai modificando il valore di myObject, devi utilizzare gli accessor per assicurarti che tutti gli altri oggetti che osservano il valore di quella proprietà vengano correttamente notificati. In altre parole:

// Not changing the value of myObject, so no accessor needed 
[someMutableArray addObject:myObject]; 

// Changes the value, so you need to use the accessor 
self.myObject = newObject;  
[self setMyObject:newObject]; // Exactly identical to the previous line. 

In generale, tuttavia, c'è poco overhead; Preferisco usare sempre gli accessori, anche all'interno dello stesso oggetto. (Naturalmente, c'è un argomento su come usarli negli inizializzatori, ma questo è un problema separato.)

3

Hrm, non posso dire di essere d'accordo con Mark o Cinder6.

Bene, sono d'accordo nella prima parte. :-) self.foo sta invocando il metodo -foo. Semplice foo sta accedendo al ivar foo.

Nella maggior parte dei casi è necessario seguire sempre i metodi.Sono lì per allontanarti dall'archiviazione reale e da qualsiasi altro comportamento che potrebbe essere necessario. Pensa a cosa succede se in seguito hai sottoclassato la tua classe. Per la maggior parte si desidera chiamare i propri metodi pubblici nei luoghi in cui si accede alle funzionalità che coprono.

L'eccezione è nell'oggetto init e teardown, e all'interno degli accessors di proprietà stessi quando non li sintetizza. Durante l'inizializzazione e il teardown degli oggetti, è necessario non voler richiamare le implementazioni dei metodi in sottoclasse, poiché questi metodi non devono avere a che fare con l'oggetto nel suo stato parzialmente impostato.

0

Non c'è risposta tagliata e secca. Tuttavia, ricorda che l'ottimizzazione prematura è cattiva. In Cocoa on the Mac o su iPhone, l'uso di accessors/properties deve essere conforme a KVO. La conformità KVO è necessaria affinché Core Data e Cocoa Bindings funzionino automaticamente. In Core Data, non è solo necessario garantire KVO quando si modificano le proprietà, ma anche quando si accede a loro.

È inoltre consigliabile utilizzare accessors/properties quando si desidera garantire il comportamento di gestione della memoria delle proprietà, vale a dire, sempre quando si imposta un ivar per utilizzare il setter o la notazione dei punti e in base al modello di gestione della memoria che si segue , per usare sempre accessorie/proprietà quando si ottiene un ivar.

Esistono diversi modelli di gestione della memoria. Tutti quelli non interrotti assicurano che un oggetto restituito da un accessore sopravviverà almeno alla fine del campo di autorelease corrente. Significa che l'oggetto viene esplicitamente trattenuto e autorizzato automaticamente nell'ambito di autorelease corrente. Il metodo raccomandato da Apple lo fa esplicitamente nella getter:

- (id)foo {return [[foo retain] autorelease]; } 
- (void)setFoo:(id)aFoo { 
    if(! [aFoo isEqual:foo]) { 
    [foo release]; 
    foo = [aFoo retain]; 
    } 
} 

E 'implicito che è il modello seguono nelle loro funzioni di accesso sintetizzati. Personalmente, preferisco autorelease nel setter:

- (id)foo {return foo;} 
- (void)setFoo:(id)aFoo { 
    [foo autorelease]; 
    foo = [aFoo retain]; 
} 

Questa autoreleasees il valore precedente prima di sostituirla con il nuovo valore. Ciò ha esattamente lo stesso effetto di mantenere e autoreleasing nel getter, ma richiede che l'oggetto venga aggiunto a un pool di autorelease solo una volta. La maggior parte delle volte ha un conteggio di ritenzione di uno e non è autorizzata, quindi non andrà da nessuna parte, non importa cosa succede. Se la proprietà viene sostituita durante un codice che è ancora in attesa (ad esempio in un callback delegato), non scomparirà da esso.

Ciò significa che l'utilizzo di accessor/proprietà ti darà la certezza che i tuoi oggetti saranno intorno a quando ne avrai bisogno senza che qualche altra parte del codice li rilasci da sotto di te.

L'ultimo e migliore motivo per utilizzare sempre accessor/proprietà è che fa un minor numero di presupposti per ogni proprietà: che esiste un ivar sottostante per quella proprietà, e che ha lo stesso nome (immagino siano due ipotesi) . Forse in futuro vorrai sostituire un ivar con un accessorio derivato. La notazione della proprietà continuerà a funzionare. Forse vuoi rinominare l'ivar; la proprietà continuerà a funzionare. Fortunatamente, si può fare affidamento sul refactoring in Xcode, ma perché preoccuparsi?

Il punto di programmazione orientata agli oggetti è utilizzare le interfacce definite sulla classe. Non c'è una buona ragione (sebbene ci siano molti pregiudizi e razionalizzazioni) che una classe ignori la propria interfaccia. Ogni metodo, ad eccezione degli stessi accessors, dovrebbe, nel caso generale, considerare l'oggetto come sacrosanto e il suo stato interno come privato. Scrivi ogni metodo come se fosse in una categoria o in una sottoclasse e tratti Ivars come stato privato, a meno che le specifiche esigenze di progettazione non siano dirette diversamente. Ci sono molti buoni motivi per accedere direttamente a ivars, ma sono determinati caso per caso.

+0

I metodi getter/setter non sono identici a quelli di Apple. Il tuo getter è fondamentalmente quello che useresti per una proprietà "assign" e il setter è per una proprietà "retain". Sono sicuro che funzioni la maggior parte del tempo, ma penso che si sbloccherà se inizierai a utilizzare i tuoi pool di autorelease. Meglio attenersi alle convenzioni usate nel resto del cacao. –

Problemi correlati