What exactly is a so called "Class Cluster" in Objective-C?
Asked Answered
B

5

94

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?

Bibliolatry answered 4/12, 2009 at 0:48 Comment(2)
Oops, next time i'll think to add a link for that term. If you would have commented on the answer to you previous question i'd have responded there.Nurture
FWIW: recently (Dec 2013) Apple recommended using Class Clusters as a way to handle backward-compatibilty to iOS 6 while using iOS 7. This was on Apple Tech Talks 2013/Berlin in the session "Architecting Modern Apps, Part 2". Apple said that they will be posting videos of the sessions shortly after the last event (17. Dec). So maybe this will help to understand Class Clusters within the actual context of the iOS 6/7 changes.Berseem
M
44

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.

Madai answered 4/12, 2009 at 0:50 Comment(2)
roflmao. thanks. gonna google next time. thought if its not in my fat books, it can only be on your heads ;)Bibliolatry
The one thing this link is missing is an explanation on how to best alter the implementation for ARC.Orometer
P
195

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
Parnassus answered 17/3, 2010 at 1:38 Comment(7)
While the other answers were good providing doc & book links, I like this because it makes it nice and simple to see how to actually do this. ThanksSuperload
This example is good but in a typical Factory pattern the subclasses are public. In a Class cluster the subclasses are private. developer.apple.com/library/ios/documentation/general/…Asti
Are the subclasses private by convention or actually private?Saturniid
@AdriàNavarro They are not visible to the outside since they are declared in the .m-file.Sal
(1) How safe is it to release self in an 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
Needs updating for iOS 8!Orometer
@Luo You're right. In real life, +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
M
44

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.

Madai answered 4/12, 2009 at 0:50 Comment(2)
roflmao. thanks. gonna google next time. thought if its not in my fat books, it can only be on your heads ;)Bibliolatry
The one thing this link is missing is an explanation on how to best alter the implementation for ARC.Orometer
T
26

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.

Tug answered 4/12, 2009 at 2:4 Comment(2)
+1 For quoting an answer from an Objective-C book, particularly given the original question. That's a good book, too.Gean
(+1) for the excellent definition. The problem I have with calling this a "Factory" pattern is that such a name focuses on just the creation of objects, not the under-the-hood interactions of the private subclasses as managed by the abstract superclass. Indeed, even calling this superclass "abstract" could be misleading as it is in fact quite (internally) dependent upon its own subclasses, and is therefore not a normal abstract class which generally does not know anything about its subclasses.Cressler
H
18

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

Heeled answered 15/4, 2014 at 20:46 Comment(0)
G
7

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.

Gustafsson answered 4/12, 2009 at 2:0 Comment(3)
Ironically, in practice, only one concrete class per cluster is ever used anymore — NSCF{Array|String|Number} — and the implementation changes are internal to that class. That's as far as I know, anyway. Even NSArray and NSMutableArray instances show up the same class.Tragedy
@Tragedy - how can this be the case? If a NSMutableArray and NSArray reported themselves to be the same class wouldn't [myArray isKindOfClass:[NSMutableArray class]] return YES even though it should not?Trackman
@Robert: And indeed that was the case at the time of my comment. Nowadays Apple has replaced NSCFArray with __NSArrayM and __NSArrayI, so I think it's no longer so, but I still wouldn't feel comfortable depending on it, as they could always change it again.Tragedy

© 2022 - 2024 — McMap. All rights reserved.