2012-02-19 17 views
6

Hay dos opciones para los constructores en Objective C/Cacao:¿Por qué usaría un constructor de método de clase versus alloc/init?

1. Clase Constructor

Product *product = [Product productWithIdentifier:@"Chocolate"]; 
// Use product 

2. Alloc/init Constructor

Product *product = [[Product alloc] initWithIdentifier:@"Chocolate"]; 
// Use product 
[product release]; 

Lo que hago

  • Tiendo a utilizar el método de clase solo porque se ve más limpio y no necesita una versión.
  • Veo mucho alloc/init, ¿cuál es la ventaja de hacerlo de esta manera?

Mi pregunta

  • Cuál es preferible? ¿O es solo una cuestión de gusto?

Código

Para el contexto, el producto de clase tendría la siguiente:

+(Product *)productWithIdentifier:(NSString *)identifier_ { 
    return [[[[self class] alloc] initWithIdentifier:identifier] autorelease]; 
} 

-(Product *)initWithIndentifier:(NSString *)identifier_ { 
    self = [super init] 
    if (self) { 
     identifier = identifier_; 
    } 
    return self; 
} 

Respuesta

5

Si usa ARC, no hay mucha diferencia entre los dos. Si no está usando ARC, la diferencia es extremadamente importante.

La combinación alloc/init le da una referencia propietaria. Eso significa que debe release más adelante. La variante classnameWithFoo devuelve una referencia no propietaria. No puede release.

Esto sigue las convenciones de nomenclatura de Cacao habituales. Todos los métodos devuelven instancias no autorizadas (autorreleasadas), excepto los métodos que comienzan con alloc, copy, mutableCopy y new. Estas devuelven las referencias propietarias que debe release.

Cuál usar es principalmente una cuestión de gusto. Sin embargo, si necesita objetos temporales que puede eliminar rápidamente, la variante alloc da como resultado un número ligeramente menor de llamadas al método (autorelease) y, en un bucle, también reduce la huella de memoria máxima. Sin embargo, en la mayoría de los casos, este costo reducido es insignificante.

+0

Tan cerca entre estas dos respuestas, pero esto es ligeramente mejor porque menciona el problema de la huella de memoria. Pero, de nuevo, la otra respuesta menciona "encadenar" llamadas juntas. ¡Ojalá pudiera elegir ambos! –

+1

He subido la respuesta de sergio para casi compensar esto ;-) – DarkDust

5

OMI, la mayor diferencia entre los dos enfoques proviene del hecho de que el uso de un "constructor de la clase "obtienes un objeto liberado automáticamente; esta es la opción más conveniente cuando usted:

  1. asigne el objeto asignado a un retain propiedades;

  2. cuando crea objetos "temporales" (piense en los diversos métodos NSString que construyen una cadena de otra cadena: en muchos casos sucede que debe "encadenar" tales llamadas; el constructor le permite "olvidar" gestión de la memoria);

  3. cuando se agrega el objeto a algún objeto que lo retiene (piensan: addSubview)

En tales casos la ventaja sintáctica de "constructor de la clase" es más importante, pero creo que también hace que su código "más seguro" en términos de gestión de la memoria.

Por otro lado, cuando crea un objeto para asignarlo a una propiedad assign (o directamente a un ivar para el que no tiene ninguna propiedad), entonces alloc/init funcionará perfectamente y será preferible al "constructor" (IMO)

Por lo tanto, al final, depende de la forma en que va a utilizar los objetos que asigna. El constructor de clase es un método de conveniencia.

Cuestiones relacionadas