2011-11-21 17 views
5

In termini di buone pratiche di codifica Objective-C, se creo una funzione senza stato, è meglio scrivere come metodo statico di una classe o come Funzione C?Metodi statici stateless contro funzioni C in Objective-C

Ad esempio, ho uno speciale metodo di recupero del percorso file che controlla la directory Caches prima di passare al NSBundle principale. Attualmente lo ho come metodo statico in una classe Utils altrimenti vuota. Questa dovrebbe essere una funzione C?

Il motivo per cui ho scelto di utilizzare un metodo statico (per ora) è che a) è coerente con la sintassi Objective-C e b) la classe aiuta a classificare il metodo. Tuttavia, mi sento come se stessi ingannando un po ', dal momento che potrei facilmente riempire la mia classe Util con questi metodi statici stateless e finire con una brutta "classe shell", il cui unico scopo sarebbe quello di tenerli.

Quale convenzione utilizzate? Uno è "migliore" rispetto all'altro, secondo una metrica oggettiva? Grazie!

risposta

2

Se si può pensare ad una classe esistente che può essere un buon metodo, è possibile iniettare il metodo creando una categoria Objective-C. Ciò mantiene i due motivi per l'utilizzo di un metodo statico mentre non inquina lo spazio della classe con una classe extra.

Ad esempio:

@interface NSString (MyStringCategories) 
- (NSString*) myCoolMethod; 
@end 

// [StringCategories.m] 
#import "StringCategories.h" 

@implementation NSString (MyStringCategories) 
- (NSString*) myCoolMethod { 
    // do cool stuff here 
    return whateverYouLike; 
} 
@end 

Ora è possibile inviare myCoolMethod-qualsiasi stringa. Freddo!

Nel vostro caso particolare, sembra che un metodo su NSBundle potrebbe essere un'architettura appropriata. E non dimenticare, può essere un metodo di classe, quindi non è necessario creare un'istanza per chiamare il tuo metodo.

+0

Sì, provo a farlo il più spesso possibile. In questo caso, non si può pensare a uno solo: cerca il pacchetto solo se non trova il file in Caches e non è un metodo di istanza come il tipico pathForResource :, quindi (secondo me) non è un misura ideale – Archagon

+0

Quindi rendilo un metodo di classe. Il mio punto è, non è l'incapacità di pensare ad una classe esistente appropriata solo un fallimento dell'immaginazione? Potrebbe essere NSBundle, potrebbe essere NSFileManager, potrebbe essere NSString (perché si occupa di nomi di percorso), potrebbe essere qualsiasi classe che tu abbia intuitivamente sentito essere nel giusto ambito. – matt

+0

+1 Per la categoria. Personalmente penso che lo scopo di una lezione sia quello di essere istanziati. Non usare una classe come spazio dei nomi. Quindi, se hai solo metodi statici, dovresti considerare un altro approccio. – Macmade

1

Questa è una domanda abbastanza difficile a cui rispondere perché per molte persone la risposta dipenderà da quali sono le loro preferenze e gusti personali. Personalmente penso che se hai una funzione che è una funzione, cioè non ha nulla a che fare con un oggetto, non ha uno stato interno ecc. Pp. Per favore lascia che sia una funzione e non provare a racchiudere tutto ciò che puoi un oggetto solo perché stai usando un linguaggio OO e puoi farlo.

Al fine di mantenere la mia risposta breve mi permetta riferisco ad un (IMO) abbastanza buon libro:

http://www.gotw.ca/publications/c++cs.htm

So che questo è per C++, ma ci sono un bel paio di intuizioni che possono essere condiviso con altri linguaggi (specialmente Objective-C e Objective-C++) specialmente dalla parte chiamata "Class Design and Inheritance". Lì troverai un elemento intitolato "Preferisci scrivere le funzioni non amiche di non membri".

Linea di fondo: "Funzioni nonfriend non appartenenti alla Chiesa migliorare incapsulamento riducendo al minimo le dipendenze [...] Hanno anche rompere le classi a parte monolitici [...] [e] di migliorare genericità [...]".

Penso che ci sia del vero in quell'articolo.

1

Se non esiste una classe a cui associare in modo chiaro, quindi uso una funzione. Uso anche le funzioni per questi bit di utilità perché possono essere rimossi se non utilizzati o referenziati. A tale riguardo, è anche utile utilizzare una funzione perché un errore di collegamento è migliore di un errore di runtime (anche nel file .m è stato accidentalmente omesso dalla build o se è stato fatto riferimento a un altro metodo aggiornato esternamente).Un problema con i simboli ObjC è che non vengono rimossi, quindi portano naturalmente una grande quantità di dipendenze - tutti i metodi e le classi objc e i metodi di categoria richiesti devono esistere nel binario finale. Questo non è un problema con programmi o librerie veramente piccoli, ma guadagna rapidamente peso con sistemi e librerie di medio/grandi dimensioni.

Tutto ciò non ha bisogno di essere dichiarato in un @interface - in particolare con sistemi più grandi in cui tutte quelle dichiarazioni trasformeranno davvero le interdipendenze in spaghetti. Rispetto ai metodi, le funzioni sono più veloci, più piccole, possono essere ottimizzate meglio dal compilatore o durante il collegamento e possono essere eliminate se non referenziate.

Se è necessario il polimorfismo, appartiene solo a una classe per l'organizzazione o la convenienza, quindi una classe o un metodo di istanza è spesso una scelta migliore.

Inoltre, minimizzo la dichiarazione dei metodi di categoria per gli stessi motivi. Quando usi le funzioni, puoi facilmente scrivere un metodo wrapper dove ne hai bisogno e ottenere il meglio da entrambi i mondi.