I was reading that NSArray is just such a thing. Sounds heavy. I have 7 really fat books here on my desk about Objective-C, Cocoa and C. None of them mention Class Cluster at all, at least I can't find it in the Index at the back of the books. So what's that?
From Apple's docs.... In short it's a design pattern used in the Foundation framework, which is probably why it's not mentioned in ObjC books.
A class cluster is an architecture that groups a number of private, concrete subclasses under a public, abstract superclass. The grouping of classes in this way provides a simplified interface to the user, who sees only the publicly visible architecture.
I don't know what is in the CDP that Steve referenced but basically the Objective-C Class Cluster is a construct that supports implementing the abstract Factory pattern.
The idea is simple: You want to provide a Factory (Cluster) interface that, with minimal description, manufactures and returns a specific concrete instance of a Factory Object that satisfies the behavior of the cluster family described by the Factory (Cluster) interface.
A simple concrete example: This example provides a Laugh factory that produces concrete classes of specific laughter types (e.g. Guffaw, Giggle). Pay attention to the Laugh initWithLaughter: method.
In Laugh.h:
#define kLaughWithGuffaw 1
#define kLaughWithGiggle 2
@interface Laugh: NSObject {}
- (Laugh *) initWithLaughter:(NSUInteger) laughterType;
- (void) laugh;
@end
In 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
.m-file
. –
Sal init
method, and return something else? Are there any code examples from Apple where they do this? (2) Also, you are presumably creating an instance with code such as [[Laugh alloc] initWithLaughter:kLaughWithGiggle]
. Notice how Laugh
is being unnecessarily allocated, since it will be released immediately after this call. Why do it this way when you can create a class method such as [Laugh laughWithLaughter:kLaughWithGiggle]
which gives you all the advantages of private subclasses, while avoiding issues 1 & 2 above? –
Luo +alloc
returns a singleton factory class that implements the various -initWith:
methods. The factory class's -initWith:
methods are then responsible for allocating and initializing a concrete subclass based on the given method parameters, if necessary, or in some cases may not allocate anything at all (such as -[NSString initWithString:]
). You can try it by inspecting at the return value of +[NSString alloc]
, +[NSArray alloc]
, etc. –
Slacks From Apple's docs.... In short it's a design pattern used in the Foundation framework, which is probably why it's not mentioned in ObjC books.
A class cluster is an architecture that groups a number of private, concrete subclasses under a public, abstract superclass. The grouping of classes in this way provides a simplified interface to the user, who sees only the publicly visible architecture.
From programming in objective c by Stephen Kochan on page 498 in the glossary, cluster:
An abstract class that groups a set of private concrete subclasses, providing a simplified interface to the user through the abstract class.
Class clusters provide a single public interface to a group of concrete, private subclass implementations. An objective-c programmer uses class clusters often and rarely realizes it - and this is the whole point of a class cluster. A class cluster's job is to hide the complexity of implementation detail behind a public interface.
Many of the Foundation classes are class clusters, such as NSString, NSArray, NSDictionary, and NSNumber. When you call [NSString stringWithFormat:]
the class cluster is giving you some concrete class that implements the NSString
interface. It could be an NSConcreteString
, NSCFString
, NSFooBarString
, etc. Which the class cluster gives you is based on the constructor or initializer you are calling and the arguments.
Because of this, class clusters are one of the most empowering concepts in Objective-C programming.
- Very easy to implement
- Easy to change the underlying implementation without changing the code that calls it.
- Easy to provide different concrete implementations at runtime (i.e. test resources or mock objects)
- Because of the above, easy to test and refactor
If you are coming from other languages you may be familiar with the Gang of Four patterns. Class clusters have elements of both the abstract factory and the facade patterns.
Apple's public documentation covers class clusters (and how to implement and extend them) quite extensively. Unfortunately, I have found that for many iOS developers this and other Cocoa-specific patterns are a blind spot.
Cocoa Core Competencies: Class cluster
Cocoa Fundamentals Guide: Class Clusters
Examples of how to implement your own class clusters are available on GitHub
The NSArray class cluster isn't "heavyweight", it's a way for any number of implementations of an array class to be used without your code knowing or caring about the particular implementation. Under the hood, there are concrete subclasses of NSArray that are appropriate to different use cases, such as large, sparse arrays, or arrays containing a specific number of elements that are known at compile time.
NSArray, NSString, and NSNumber are the class clusters you'll most often encounter.
[myArray isKindOfClass:[NSMutableArray class]]
return YES even though it should not? –
Trackman © 2022 - 2024 — McMap. All rights reserved.