2012-05-10 12 views
9

Supongamos que estoy haciendo una clase Objective-C que representa una fracción, y quiero crear versiones inmutables y mutables.¿Cuál es la forma más eficiente de hacer versiones inmutables y mutables de una clase object-c?

Siguiendo los patrones en el marco de Foundation, es posible que espere ver el método fractionByAddingFraction: en la versión inmutable y addFraction: en la versión mutable.

La paradoja que me encuentro es cómo incluir solo la lógica de adición de fracciones una vez entre las dos clases. Parece que el método inmutable fractionByAddingFraction: necesita conocer (y utilizar) el método addFraction: mutable para evitar la duplicación de código, y aún así incluir los métodos mutables en la implementación de la clase inmutable significa que podrían ser invocados sobre lo inmutable objeto, que derrota el punto.

¡Una breve explicación (o mejor aún, una continuación de este ejemplo simplificado) sería muy apreciada!

+4

Su ejemplo de clase parece representar un _value object_, por lo que no creo que deba proporcionar una versión mutable para él. __ Hazlo inmutable .__ –

+0

@ Jordão Para este ejemplo en particular, tienes toda la razón. Sentí que esta era la manera más fácil y concisa de explicar mi confusión sobre el concepto en general (ya que se refiere a clases más complicadas). ¿Alguna idea de cómo se haría independientemente? – user1385983

Respuesta

3

Su enfoque es correcto (si realmente necesita una subclase mutable, que debe evitar a menos que realmente la necesite). No estoy del todo claro en dónde está llegando la confusión. Lo más fácil sería implementar addFraction: usando fractionByAddingFraction:. Sería un poco ineficiente, pero esa es la dirección que tendría más sentido. Algo así como:

- (void)addFraction:(Fraction *)anotherFraction { 
    Fraction *newFraction = [self fractionByAddingFraction:anotherFraction]; 
    self.internalStuff = newFraction.internalStuff; 
} 

Pero por lo general es probable que se ocuparía de esta manera más eficiente con alguna función privada _GetInternalStuffByAddingInternalStuffs() que ambas clases usarían.

+0

Gracias por las sugerencias. Había evitado el primer enfoque simplemente porque, como mencionaste, puede ser ineficiente crear un nuevo objeto cada vez que se cambian algunos de sus componentes. Tu idea de hacer una función privada parece ser una buena alternativa. Sin embargo, me pregunto dónde estaría ubicada idealmente la función para acceder a las implementaciones de ambas clases, pero inaccesible para cualquier otra cosa (lo cual excluye ponerla en un encabezado). – user1385983

+0

Esto normalmente se hace con un encabezado privado como Fraction + Private.h. Tenga en cuenta que es posible que desee considerar abandonar el formulario mutable si es este tipo de cosas. Observe cómo NSNumber no tiene forma mutable. A menos que esté creando muchos de ellos muy rápido, la simplicidad y la seguridad de subprocesos de los objetos de valor los hace muy atractivos. Incluso si los haces muy rápido, puedes almacenarlos en caché. NSNumber almacena en caché los enteros -1-12 como singletons como recuerdo. Puede hacer ese tipo de almacenamiento en caché más fácilmente con objetos inmutables. Pero lo anterior es cómo lo manejas cuando necesitas mutabilidad. –

+0

Recuerde que puede ver cómo se implementan los objetos CoreFoundation subyacentes: http://opensource.apple.com/source/CF/CF-635/CFArray.c. –

0

Las implementaciones principales de las colecciones de la Fundación engañan: solo hay una implementación, que es una subclase de NSMutableFoo, y tiene una bandera de mutabilidad privada. Esto significa que el código del cliente no puede probar si un objeto en particular es mutable o no, pero eso nunca sería una buena idea de todos modos, excepto tal vez para la depuración y las afirmaciones.

+0

¿Entiendo correctamente que 'NSFoo' sería una subclase de 'NSMutableFoo', y que 'NSMutableFoo' contendría todos los métodos para ambas clases, sin embargo, limitaría la capacidad de su subclase inmutable para usar las variables basadas en la bandera privada? – user1385983

+0

'NSFoo' no es una subclase de' NSMutableFoo', no. La relación es generalmente 'NSFoo' ←' NSMutableFoo' ← 'NSCFFoo', donde' NSCFFoo' es una implementación concreta. Los métodos mutantes de 'NSCFFoo' comprueban la bandera mutable y lanzan una excepción si es inmutable. (La realidad es en realidad más compleja que esto debido a la creación de puentes sin costo, pero así es como funcionaría sin CF involucrado). Para sus propias clases, probablemente llamaría a la subclase concreta algo así como 'XYConcreteFoo'. –

Cuestiones relacionadas