Reputation: 831
Let's say I have a motheclass (abstract or not) Item and two subclasses ItemA et ItemB which both inherit from Item
All instances are created based on a NSDictionary through the following method
-(id)initWithJSON:(NSDictionary *)d{
//first instantiate common properties from the motherclass
if ([super initWithJSON:d]){
//Do specific stuff for the subclass
}
return self;
}
Now let's say I fetch from a webservice an array that can contain both ItemA & Item to be created.
Currently what I do is that use a if/then condition to determine which subclass I will instantiate based on the dictionary content, for instance :
[(NSArray*)data enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([obj[@"kind"] isEqualToString:@"A"])
[interactions addObject:[[ItemA alloc] initWithJSON:obj]];
else if ([obj[@"kind"] isEqualToString:@"B"])
[interactions addObject:[[ItemB alloc] initWithJSON:obj]];
else
[interactions addObject:[[Item alloc] initWithJSON:obj]];
}];
Now my point is the following : is there a way to have only one line of code that will - by default - instantiate an Item object, and based on the kind an ItemA or an ItemB In other words, can I write some code in the init method of the motherclass Item to instantiate a subclass instead if some conditions are fulfilled in the NSDictionary parameters which is parsed ?
Thanks
Upvotes: 0
Views: 71
Reputation: 17278
Have a look at NSClassFromString .
Example pseudo-code:
NSString *className = [NSString stringWithFormat:@"Item%@", obj[@"kind]];
Class metaClass = NSClassFromString(className);
*instance = [[metaClass alloc] initWithJSON:obj];
You then encapsulate this behavior in a static class factory method to your mother class. See Daij-Djan's answer for details.
Upvotes: 1
Reputation: 50089
in your mother class, add a convenience method like this:
+(instancetype)itemWithJSON:(NSDictionary *)obj {
id item;
if ([obj[@"kind"] isEqualToString:@"A"]) {
item = [[ItemA alloc] initWithJSON:obj];
} else if ([obj[@"kind"] isEqualToString:@"B"]) {
item = [[ItemB alloc] initWithJSON:obj];
} else {
item = [[Item alloc] initWithJSON:obj];
}
return item;
}
then use it like this:
[(NSArray*)data enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[interactions addObject:[Item itemWithJSON:obj]];
}];
Upvotes: 2