Reputation: 6296
I'm a bit new to Objective-C, and I've been trying to do something that apparently isn't allowed, even though it's common practice in other languages (I think).
As a specific example, I want to subclass NSMutableArray
to make a SortedMutableArray
that always maintains itself in a sorted state. So I subclassed NSMutableArray
in the usual manner, adding a NSComparator
property that determines the sort order. I overrode the addObject:
method to insert objects in a sorted manner:
- (void) addObject:(id)anObject {
for (int i = 0; i < [self count]; ++i) {
NSComparisonResult result = (NSComparisonResult)self.comparator([self objectAtIndex:i], anObject);
if (result == NSOrderedDescending || result == NSOrderedSame) {
[super insertObject:anObject atIndex:i];
break;
}
else {
if (result != NSOrderedAscending) {
[NSException raise:@"InvalidBlockException" format:@"Block must return one of NSOrderedDescending, NSOrderedAscending, or NSOrderedSame"];
}
}
}
}
and everything compiles great. But when I run the program, I get an error indicating that insertObject:atIndex:
is now abstract and needs to be implemented. Reading the documentation, it lists several methods that must be implemented in any subclass of NSMutableArray
, one of which is indeed insertObject:atIndex:
. But I don't need to change the functionality of insertObject:atIndex:
; I want it to word exactly as it does in NSMutableArray
. Is there a way that I can do this (in general, too, not just for this specific problem)? Why must certain methods be implemented in subclasses like this? Doesn't that kind of defeat one of the purposes of inheritance, code reuse? I've never seen anything like this in other languages, where a method is concrete in a superclass but becomes abstract when it is subclassed. Does this pattern/concept have a name?
Thanks in advance for any help, and I'm sorry if I'm duplicating another question, but I didn't know what to search for other than "subclass" in the objective-c tag, which gave too many results to find what I was looking for.
Upvotes: 0
Views: 802
Reputation: 345
You shouldn't be subclassing NSMutableArray, look up categories. It provides a way to add newer methods to classes
Upvotes: 1
Reputation: 3572
See Dave DeLong's post about why this is a not a good idea.
If you really want to do something like this, you could try, uhmm, "fake-subclassing" it.
in the .h file,
...
NSMutableArray *mutableArray;
...
@property (nonatomic, retain) NSMutableArray *mutableArray;
...
- (void) addObject:(id)anObject;
in the .m file,
...
@synthesize mutableArray;
...
- (void) addObject:(id)anObject {
[mutableArray addObject:id];
[mutableArray sortUsingSelector:@selector(yourSortingSelector);
}
- (NSMutableArray)mutableArray {
return mutableArray;
}
...
Which works and everything. My colleague did a similar class to this before (we were objective-c noobs at the time, about 2-3 weeks into learning how to code).
What I would recommend, however, is to use a Key-Value Observing approach if you can. Try to listen in whenever an element is added, and sort your array when you get the notification. I haven't done this to an NSMutableArray before though, so I don't know how this will work or if it even will.
My 2 cents, hope it helps. Happy holidays! ^_^
Upvotes: 2
Reputation: 243156
Bad idea. NSArray
is actually a class cluster (which is our word for [essentially] an abstract factory). This means that when you alloc
/init
an NSArray
, you don't actually get an NSArray
back. You get (usually) an NSCFArray
, which is a private subclass.
NSMutableArray
is the same deal (it's abstract). When you alloc
/init
an NSMutableArray
, you get an NSCFArray
back that has a little internal mutable bit flipped.
The upshot of this is that subclass a class cluster is generally discouraged, because it's a bit more complex than just creating a normal subclass.
What I would recommend is to instead check out the CHDataStructures framework, which has a whole bunch of data structures that do what you're looking for already.
Upvotes: 11