views:

59

answers:

3

I have an NSMutableArray object that I want to add custom methods to. I tried subclassing NSMutableArray but then I get an error saying "method only defined for abstract class" when trying to get the number of objects with the count method. Why is the count method not inherited?

I read somewhere else that I will have to import some NSMutableArray methods into my custom class if I want to use them. I just want to add a custom method to the NSMutableArray class. So should I subclass NSMutableArray, or should I do something else?

+2  A: 

If you're just adding a custom method, use a category on NSMutableArray. It's a class cluster, so the implementation is provided by undocumented subclasses. You need to provide a few methods to generate your own subclass. However, if you just add a category then your custom method will work on all NSMutableArrays in your app.

For comparison, here's an example I wrote a while back of implementing a custom NSMutableArray subclass.

Graham Lee
I would like to comment that implementing a custom type safe NSMutableArray subclass is a waste of time. The time spend writing this custom subclass would have been better spent writing some unit-tests to validate that your *actual* application logic is sound, not add more clutter to it. Your extra code is just more code to maintain, adding only more attack vectors for bugs and security flaws without adding any real benefits to the end user.
PeyloW
@PeyloW: a fine theoretical position to take, but ultimately there is real-world code where type safety can be useful. As described in the post I wrote, you bring any failure forward to the point where it's injected, not some arbitrary later time. That reduced the attack surface by removing the possibility for malicious object substitution.
Graham Lee
@PeyloW: there's also real-world code that needs to interface to CoreFoundation. That cares about whether your mutable array implementation is actually an NSMutableArray subclass or something else; at which point your implementation had better subclass NSMutableArray.
Graham Lee
+3  A: 

Objective-C has a mechanism for adding methods to existing classes called Categories. That way you don't have to create your own subclass.

Robot K
+3  A: 

NSMutableArray is not a concrete class, it is just the abstract superclass of a class cluster. The documentation for NSMutableArray does have information about how to subclass, but also strongly advises you not to! Only subclass if you have a special need for actual storage.

A class cluster means that the actual class will be chosen at run-time. An array created empty, may not use the same class as an array created with 1000 items. The run-time can do smart choices of what implementation to use for you. In practice NSMutableArray will be a bridged CFArray. Nothing you need to worry about, but you might see it if you inspect the type of your arrays in the debugger, you will never see NSArray, but quite often NSCFArray.

As mentioned before no subclassing is not the same as not being able to extend a class. Objective-C has the concept of categories. A category is similar to what other programming languages call mix-ins.

If you for example want a convenience method on NSMutableArray to sort all members on a property, then define the category interface in a .h file as such:

@interace NSMutableArray (CWFirstnameSort)
-(void)sortObjectsByProperty:(NSString*)propertyName;
@end

And the implementation would be:

@implementation NSMutableArray (CWFirstnameSort)
-(void)sortObjectsByProperty:(NSString*)propertyName;
{
    NSSortDescriptor* sortDesc = [NSSortDescriptor sortDescriptorWithKey:propertName ascending:YES];
    [self sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];
}
@end

Then use it simply as:

[people sortObjectsByProperty:@"firstName"];
PeyloW