¿Qué es exactamente un "grupo de clases" en Objective-C?

91

Estaba leyendo que NSArray es tal cosa. Suena pesado. Tengo 7 libros realmente gordos aquí en mi escritorio sobre Objective-C, Cocoa y C. Ninguno de ellos menciona Class Cluster en absoluto, al menos no puedo encontrarlo en el Índice al final de los libros. Entonces, ¿qué es eso?

rana abierta
fuente
Vaya, la próxima vez pensaré en agregar un enlace para ese término. Si hubiera comentado la respuesta a su pregunta anterior, habría respondido allí.
Georg Fritzsche
2
FWIW: recientemente (diciembre de 2013) Apple recomendó usar Class Clusters como una forma de manejar la compatibilidad con versiones anteriores de iOS 6 mientras se usa iOS 7. Esto fue en Apple Tech Talks 2013 / Berlín en la sesión "Arquitectura de aplicaciones modernas, Parte 2". Apple dijo que publicarán videos de las sesiones poco después del último evento (17 de diciembre). Entonces, tal vez esto ayude a comprender los clústeres de clases dentro del contexto real de los cambios de iOS 6/7.
Brainray

Respuestas:

42

A partir de documentos de Apple ... . En resumen, es un patrón de diseño utilizado en el marco de la Fundación, por lo que probablemente no se menciona en los libros de ObjC.

Un clúster de clases es una arquitectura que agrupa una serie de subclases concretas privadas en una superclase abstracta pública. La agrupación de clases de esta manera proporciona una interfaz simplificada para el usuario, que solo ve la arquitectura públicamente visible.

eco
fuente
1
roflmao. Gracias. voy a google la próxima vez. Pensé que si no está en mis libros gordos, solo puede estar en sus cabezas;)
openfrog
1
Lo único que le falta a este enlace es una explicación sobre cómo modificar mejor la implementación de ARC.
Hipérbole
193

No sé qué hay en el CDP al que hizo referencia Steve, pero básicamente el clúster de clase Objective-C es una construcción que admite la implementación del patrón abstracto de fábrica .

La idea es simple : desea proporcionar una interfaz Factory (Cluster) que, con una descripción mínima, fabrique y devuelva una instancia concreta específica de un Factory Object que satisfaga el comportamiento de la familia de clúster descrita por la interfaz Factory (Cluster).

Un ejemplo concreto simple : este ejemplo proporciona una fábrica de risas que produce clases concretas de tipos de risa específicos (por ejemplo, Guffaw, Giggle). Preste atención al método Laugh initWithLaughter : .

En Laugh.h:

#define kLaughWithGuffaw  1
#define kLaughWithGiggle  2

@interface Laugh: NSObject {}
- (Laugh *) initWithLaughter:(NSUInteger) laughterType;
- (void) laugh;
@end

En Laugh.m:

@interface Guffaws:Laugh {}
- (void) laugh;
@end

@interface Giggles:Laugh {}
- (void) laugh;
@end

@implementation Laugh
- (Laugh *) initWithLaughter:(NSUInteger) laugherType {
    id instanceReturn=nil;
    ; // Removed for ARC [self release]
    if ( laughterType == kLaughWithGuffaw )
        instanceReturn = [[Guffaws alloc]init];
    else if( laughterType == kLaughWithGiggle )
        instanceReturn = [[Giggles alloc]init];
    else
        ; // deal with this
    return instanceReturn;
}

- (void) laugh {
    NSLog(@"Humbug");
}
@end

@implementation Guffaws
    - (void) laugh {
        NSLog(@"OH HA HA HOWAH HA HA HA");
    }
@end

@implementation Giggles
    - (void) laugh {
        NSLog(@"Tee hee");
    }
@end
Frank C.
fuente
24
Si bien las otras respuestas fueron buenas al proporcionar enlaces a documentos y libros, me gusta esto porque hace que sea agradable y simple ver cómo hacer esto realmente. Gracias
jamone
Este ejemplo es bueno, pero en un patrón Factory típico, las subclases son públicas. En un clúster de clases, las subclases son privadas. developer.apple.com/library/ios/documentation/general/…
maxpower
1
@ AdriàNavarro No son visibles al exterior ya que están declarados en el .m-file.
hfossli
4
(1) ¿Qué tan seguro es liberarse en un initmétodo y devolver algo más? ¿Hay ejemplos de código de Apple donde hacen esto? (2) Además, presumiblemente está creando una instancia con un código como [[Laugh alloc] initWithLaughter:kLaughWithGiggle]. Observe cómo Laughse asigna innecesariamente, ya que se liberará inmediatamente después de esta llamada. ¿Por qué hacerlo de esta manera cuando puede crear un método de clase como el [Laugh laughWithLaughter:kLaughWithGiggle]que le brinda todas las ventajas de las subclases privadas, mientras evita los problemas 1 y 2 anteriores?
Sensible
1
@Senseful Tienes razón. En la vida real, +allocdevuelve una clase de fábrica singleton que implementa los diversos -initWith:métodos. Los -initWith:métodos de la clase de fábrica son responsables de asignar e inicializar una subclase concreta en función de los parámetros del método dados, si es necesario, o en algunos casos pueden no asignar nada en absoluto (como -[NSString initWithString:]). Se puede probar mediante la inspección en el valor de retorno de +[NSString alloc], +[NSArray alloc], etc.
Darren
25

De la programación en el objetivo c de Stephen Kochan en la página 498 del glosario, grupo:

Una clase abstracta que agrupa un conjunto de subclases concretas privadas, proporcionando una interfaz simplificada al usuario a través de la clase abstracta.

t011phr33
fuente
5
+1 Por citar una respuesta de un libro de Objective-C, particularmente dada la pregunta original. También es un buen libro.
Quinn Taylor
(+1) por la excelente definición. El problema que tengo al llamar a esto un patrón de "Fábrica" ​​es que ese nombre se centra solo en la creación de objetos, no en las interacciones ocultas de las subclases privadas administradas por la superclase abstracta. De hecho, incluso llamar "abstracta" a esta superclase podría inducir a error, ya que de hecho depende bastante (internamente) de sus propias subclases y, por lo tanto, no es una clase abstracta normal que generalmente no sabe nada sobre sus subclases.
devios1
18

Los clústeres de clases proporcionan una única interfaz pública a un grupo de implementaciones de subclase privadas concretas. Un programador de objetivo-c usa grupos de clases a menudo y rara vez se da cuenta, y este es el objetivo de un grupo de clases. El trabajo de un clúster de clases es ocultar la complejidad de los detalles de implementación detrás de una interfaz pública.

Muchas de las clases Foundation son grupos de clases, como NSString, NSArray, NSDictionary y NSNumber. Cuando llamas [NSString stringWithFormat:]al clúster de clases, obtienes una clase concreta que implementa la NSStringinterfaz. Podría ser una NSConcreteString, NSCFString, NSFooBarString, etc., que el grupo de clase le da se basa en el constructor o el inicializador que está llamando y los argumentos.

Debido a esto, los grupos de clases son uno de los conceptos más empoderadores en la programación de Objective-C.

  • Muy fácil de implementar
  • Fácil de cambiar la implementación subyacente sin cambiar el código que lo llama.
  • Fácil de proporcionar diferentes implementaciones concretas en tiempo de ejecución (es decir, recursos de prueba u objetos simulados)
  • Debido a lo anterior, fácil de probar y refactorizar

Si viene de otros idiomas, es posible que esté familiarizado con los patrones de la Banda de los Cuatro. Los grupos de clases tienen elementos tanto de la fábrica abstracta como de los patrones de fachada.

La documentación pública de Apple cubre los grupos de clases (y cómo implementarlos y extenderlos) de manera bastante extensa. Desafortunadamente, he descubierto que para muchos desarrolladores de iOS, este y otros patrones específicos de Cocoa son un punto ciego.

Competencias básicas del cacao: grupo de clases

Guía de conceptos básicos de cacao: grupos de clases

En GitHub hay ejemplos de cómo implementar sus propios clústeres de clases.

sofocar
fuente
7

El clúster de clases NSArray no es "pesado", es una forma de utilizar cualquier número de implementaciones de una clase de matriz sin que su código sepa o se preocupe por la implementación en particular. Bajo el capó, hay subclases concretas de NSArray que son apropiadas para diferentes casos de uso, como matrices grandes y dispersas o matrices que contienen una cantidad específica de elementos que se conocen en el momento de la compilación.

NSArray, NSString y NSNumber son los grupos de clases que encontrará con más frecuencia.

NSResponder
fuente
6
Irónicamente, en la práctica, solo se usa una clase concreta por clúster - NSCF {Array | String | Number} - y los cambios de implementación son internos a esa clase. Eso es lo que yo sé, de todos modos. Incluso las instancias de NSArray y NSMutableArray muestran la misma clase.
Chuck
1
@Chuck, ¿cómo puede ser este el caso? Si NSMutableArray y NSArray informaran que son de la misma clase, ¿no [myArray isKindOfClass:[NSMutableArray class]]devolverían SÍ aunque no debería?
Robert
1
@Robert: Y de hecho ese era el caso en el momento de mi comentario. Hoy en día Apple ha reemplazado NSCFArray con __NSArrayM y __NSArrayI, así que creo que ya no es así, pero todavía no me sentiría cómodo dependiendo de él, ya que siempre podrían volver a cambiarlo.
Chuck