2010-03-10 10 views
5

Uno di questi due modi per creare e inizializzare un oggetto è preferibile?Obiettivo C: metodo preferito per creare e inizializzare un oggetto

MyClass oClass = [[MyClass alloc] init]; 
oClass.length = 5; 
oClass.text = @"Hello"; 

o utilizzando un metodo di classe che contiene circa lo stesso codice, ma è simile al seguente:

MyClass oClass = [MyClass myClassWithLength:(int) 5 andText:(NSString *) @"Hello"]; 

Odio quando vedo le cose fatte più di un modo e non ho idea se uno è meglio dell'altro, o perché!

+0

intendi [MyClass myClassWithLength: ...? – Ross

+2

Non c'è mai un metodo di classe che verrà chiamato 'initWith ...' - i metodi init sono sempre metodi di istanza. Sarà sempre '[[MyClass alloc] initWith ...]'. Le classi a volte offrono dei costruttori di convenienza come quelli di Ross, però. Giusto per essere chiari. – Chuck

risposta

8

Non essere un nemico. :-)

A proposito, sto supponendo che volevi dire:

(Edit: rimossi calchi inutili)

MyClass oClass = [[MyClass alloc] initWithLength:5 andText:@"Hello"]; 

La ragione per più di init ... metodi è quello di rendere è più conveniente per gli sviluppatori creare istanze correttamente inizializzate. Ad esempio, se scopri che gli sviluppatori spesso hanno bisogno di creare istanze di MyClass con una lunghezza e un testo, ti semplifichi la vita fornendo un'API che permetta loro di farlo in un unico passaggio. E se scopri che spesso gli sviluppatori devono creare istanze di MyClass con solo una stringa di testo, potresti anche fornire un metodo -initWithText:.

E se le istanze create in questo modo sono spesso utilizzate come oggetti temporanei (cioè non memorizzate in variabili di istanza o variabili statiche), è anche possibile aggiungere un metodo di classe come +myClassWithText: che restituisce un'istanza autorizzata di MyClass inizializzata con fornito stringa di testo

Quanto al quale è meglio: è sempre meglio di inizializzare completamente un oggetto quando è possibile, quindi, se l'oggetto deve entrambi i valori di essere correttamente inizializzato, utilizzare il metodo che consente di fornire entrambi gli argomenti. E se non hai bisogno di memorizzare un riferimento all'istanza che stai creando, usa il metodo di classe di convenienza in modo che il tuo codice non debba occuparsi della gestione della memoria.

+0

Buon punto. Ma sembra che l'esempio di codice debba apparire come MyClass oClass = [[MyClass alloc] initWithLength: 5 andText: @ "Hello"]; senza (int) e (NSString *) prima degli argomenti corrispondenti ... – Wildcat

2

Se l'oggetto non è utilizzabile senza lunghezza e testo, la seconda opzione potrebbe essere migliore. Se quei campi sono opzionali, allora il primo è migliore.

Tuttavia, non penso che ci sia una verità assoluta a questa domanda.

+1

E spesso una classe fornirà entrambe le alternative, per comodità (da qui la necessità di un "inizializzatore designato" nell'implementazione della classe). –

0

Se si dispone di una classe con molte proprietà, è molto improbabile inizializzarle tutte in un'unica riga di codice. Entrambi i modi funzionano bene per me.

+0

Non c'è motivo di ipotizzare un mapping uno-a-uno tra proprietà e valori iniziali, specialmente dato che + alloc garantisce che tutte le variabili di istanza (diverse da isa) sono inizializzate a zero, che per molte proprietà è un valore predefinito ragionevole. Ma nei casi in cui un numero maggiore di valori iniziali è effettivamente utile, si potrebbe prendere in considerazione l'implementazione di un metodo -initWithDictionary :. – jlehr

0

Se è disponibile un metodo initWithSomething: e si desidera fornire valori iniziali per tali proprietà, lo preferirei sempre solo perché è più semplice. Funzionerà sempre anche con versioni immutabili di una classe.

Ma nessuno dei due metodi è intrinsecamente "migliore". Le classi di solito hanno uno o due inizializzatori designati e tutti gli altri chiamano solo quelli con valori predefiniti - non necessariamente lascia intatte le proprietà dell'istanza. La documentazione per una classe dovrebbe indicare cosa fanno i suoi inizializzatori e quale è l'inizializzatore designato per la classe. Ad esempio, [[NSDate alloc] init] utilizza l'inizializzatore designato da NSDate, initWithTimeIntervalSinceReferenceDate:, per creare un oggetto data che rappresenta la data e l'ora correnti.

Per inciso, questo significa anche che quando si sottoclassa una classe, è sufficiente eseguire l'override del proprio inizializzatore designato.Dal momento che gli altri lo chiamano, ottengono il tuo nuovo comportamento gratuitamente.

Problemi correlati