2010-03-10 17 views
5

¿Es preferible una de estas dos formas de crear e inicializar un objeto?Objetivo C: forma preferida de crear e inicializar un objeto

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

o el uso de un método de clase que contiene aproximadamente el mismo código, pero se parece a esto:

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

lo odio cuando veo las cosas más de una forma y no tengo ni idea de si uno es mejor que el otro, o por qué!

+0

¿Quiere decir [MyClass myClassWithLength: ...? – Ross

+2

Nunca hay un método de clase que se llamará 'initWith ...' - los métodos init son siempre métodos de instancia. Siempre será '[[MyClass alloc] initWith ...]'. Sin embargo, las clases a veces ofrecen constructores de conveniencia como Ross. Solo para aclarar. – Chuck

Respuesta

8

No seas un enemigo. :-)

Por cierto, estoy suponiendo que quería decir:

(Editar: retirados moldes innecesarios)

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

La razón de múltiples métodos init ... es hacer es más conveniente para los desarrolladores crear instancias correctamente inicializadas. Entonces, por ejemplo, si descubre que los desarrolladores a menudo necesitan crear instancias de MyClass con una longitud y un texto, les facilita la vida al proporcionarles una API que les permite hacer eso en un solo paso. Y si encuentra que los desarrolladores también necesitan crear instancias de MyClass con solo una cadena de texto, también puede proporcionar un método -initWithText:. Y si las instancias creadas de esta manera se utilizan con frecuencia como objetos temporales (es decir, no se almacenan en variables de instancia o estáticas), también puede agregar un método de clase conveniente como +myClassWithText: que devuelve una instancia autorizada de MyClass inicializada con el proporcionado cadena de texto.

En cuanto a cuál es mejor: siempre es mejor inicializar por completo un objeto cuando sea posible, de modo que si el objeto necesita que ambos valores se inicialicen correctamente, utilice el método que le permite proporcionar ambos argumentos. Y si no necesita almacenar una referencia a la instancia que está creando, use el método de conveniencia de clase para que su código no tenga que lidiar con la administración de memoria.

+0

Buen punto. Pero parece que el ejemplo del código debería verse como MyClass oClass = [[MyClass alloc] initWithLength: 5 andText: @ "Hello"]; sin (int) y (NSString *) antes de los argumentos correspondientes ... – Wildcat

2

Si el objeto no se puede usar sin la longitud ni el texto, la segunda opción podría ser mejor. Si esos campos son opcionales, entonces el primero es mejor.

Sin embargo, no creo que haya una verdad absoluta en esta pregunta.

+1

Y a menudo una clase proporcionará ambas alternativas, por conveniencia (de ahí la necesidad de un "inicializador designado" en la implementación de la clase). –

0

Si tiene una clase con muchas propiedades, es muy poco probable que las inicialice en una sola línea de código. Ambas formas funcionan bien para mí.

+0

No hay ninguna razón para suponer un mapeo uno a uno entre propiedades y valores iniciales, especialmente dado que + alloc garantiza que todas las variables de instancia (distintas de isa) se inicializan a cero, lo que para muchas propiedades es un valor predeterminado razonable. Pero en los casos en que una gran cantidad de valores iniciales es realmente útil, puede considerar implementar un método -initWithDictionary :. – jlehr

0

Si hay disponible un método initWithSomething: y desea proporcionar valores iniciales para esas propiedades, siempre lo preferiría simplemente porque es más simple. También funcionará siempre incluso con versiones inmutables de una clase.

Pero ninguno de los métodos init es intrínsecamente "mejor". Las clases generalmente tienen uno o dos inicializadores designados y todas las demás simplemente llaman a aquellas con valores predeterminados; no necesariamente deja intactas las propiedades de la instancia. La documentación de una clase debe indicar lo que hacen sus inicializadores y cuál es el inicializador designado para la clase. Por ejemplo, [[NSDate alloc] init] usa el inicializador designado de NSDate, initWithTimeIntervalSinceReferenceDate:, para crear un objeto de fecha que represente la fecha y la hora actuales.

Dicho sea de paso, esto también significa que cuando se subclasifica una clase, solo tiene que anular su inicializador designado.Como los demás solo llaman eso, obtienen su nuevo comportamiento de forma gratuita.

Cuestiones relacionadas