2010-08-06 8 views
7

Dalla documentazione di Apple circa Memory Management:Perché shoudn't Io uso i metodi di accesso a metodi init

Gli unici luoghi che non si dovrebbe usare metodi di accesso per impostare una variabile di istanza sono i metodi init e dealloc. Per inizializzare un oggetto contatore con un oggetto numero che rappresenta lo zero, si potrebbe implementare un metodo init come segue:

per consentire un contatore per essere inizializzato con un valore diverso da zero, è possibile implementare un initWithCount: metodo come segue:

- initWithCount:(NSNumber *)startingCount { 
    self = [super init]; 
    if (self) { 
     count = [startingCount copy]; 
    } 
    return self; 
} 

Perché no?

+0

è possibile aggiungere un collegamento alla fonte della documentazione? –

+0

possibile duplicato di [Perché non dovrei usare gli Accessors Obective C 2.0 in init/dealloc? ] (http://stackoverflow.com/questions/192721/why-shouldnt-i-use-obective-c-2-0-accessors-in-init-dealloc) –

+0

@Scott: ho appena aggiunto un collegamento la domanda stessa. –

risposta

16

Vedere la risposta a this question.

Il motivo principale è perché una sottoclasse potrebbe ignorare gli accessor e fare qualcosa di diverso. Gli accessor della sottoclasse possono assumere un oggetto completamente inizializzato, cioè che tutto il codice nel metodo init della sottoclasse è stato eseguito. In realtà, nessuno di questi ha quando il tuo metodo init è in esecuzione. Allo stesso modo, le funzioni di accesso della sottoclasse possono dipendere dal fatto che il metodo dealloc della sottoclasse non è stato eseguito. Questo è chiaramente falso quando il tuo metodo dealloc è in esecuzione.

Per espandere il tuo esempio, se si fosse invece fatto

- initWithCount:(NSNumber *)startingCount { 
    self = [super init]; 
    if (self) { 
     [self setCount: [startingCount copy]]; 
    } 
    return self; 
} 

ma una sottoclasse aveva ignorato setCount: per fare qualcosa di diverso impostare la variabile di conteggio, si potrebbe essere nei guai.

1

solo da un punto di vista OOP (poiché non ho esperienza con ogg-c), non usereste i metodi dell'oggetto attualmente in costruzione. Questo è possibile in alcune lingue, ma hai già accesso alle variabili private. La costruzione dell'oggetto non è ancora completata, quindi non è pronta per essere utilizzata. Una volta che l'oggetto è costruito, si trova in uno stato buono noto (o così si presume) e può funzionare.

+0

Sì, ho capito che se hai ridefinito il metodo init che potrebbe essere un problema di auto ricorsione. Ma se si definisce un altro metodo come initWithCount, non ottengo il punto da un punto di vista tecnico. –

+0

Classe, istanza e metodi statici sono oggetti statici che vengono creati quando viene creato l'oggetto classe. Strettamente parlando, non esiste un linguaggio OOP in cui i costruttori creano istanze: sono solo metodi di istanza protetti sintatticamente che * hanno * bisogno di essere associati a un'istanza che viene creata e fornita al costruttore quando viene invocata - vale a dire che lì non è una tale lingua OOP in cui non è consentito accedere ai metodi di istanza nel costruttore quando si dispone già di un'istanza con cui lavorare. –

2

JeremyP ha fatto un buon punto. Poiché la sintassi dell'invocazione setter implica sempre "self", il cui tipo è determinato in fase di runtime, quindi un'istanza di sottoclasse può chiamare la sua versione sovrascritta di setter, se "self" è veramente un oggetto sottoclasse ...

Tuttavia, lì sono alcuni casi in cui è necessario utilizzare il setter in un inizializzatore. Questo è quando la variabile di istanza viene dichiarata all'interno di una superclasse; NON puoi accedere direttamente alla variabile di istanza, quindi devi usare il setter.

Un'altra situazione è quando la proprietà utilizza l'inizializzazione pigra. In questo caso, devi passare attraverso il getter; se non lo fai, la variabile di istanza non avrà mai la possibilità di essere inizializzata. Ad esempio, la classe EOCPerson potrebbe avere una proprietà per consentire l'accesso a un oggetto complesso che rappresenta il cervello di ogni persona. Se questa proprietà è raramente accessibile e costosi da installare, si potrebbe inizializzare pigramente nel getter, in questo modo:

- (EOCBrain*)brain { if (!_brain) { 
     _brain = [Brain new]; 
    } 
return _brain; } 

Se si dovesse accedere direttamente alla variabile di istanza e il getter non era stato ancora chiamato, cervello non sarebbe stato impostato e dovresti chiamare l'accessor per tutti gli accessi alla proprietà del cervello.

- EOC libro di Matt Galloway item7

-3

Nel giorno moderno obiettivo C, si dovrebbe essere in grado di utilizzare metodi di accesso all'interno di init. Gli errori del compilatore risulteranno RARAMENTE se non si verifica MAI più MAIUSO

Problemi correlati