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?
Objective-C has a mechanism for adding methods to existing classes called Categories. That way you don't have to create your own subclass.
From the Apple reference for NSArray, in the Methods to Override section:
Any subclass of NSArray must override the primitive instance methods count and objectAtIndex:. These methods must operate on the backing store that you provide for the elements of the collection. For this backing store you can use a static array, a standard NSArray object, or some other data type or mechanism. You may also choose to override, partially or fully, any other NSArray method for which you want to provide an alternative implementation.
As a side note, in Objective-C, there is no actual feature that allows you to declare a class as an abstract class, per se, as in Java, for instance. So, what they do instead is call something like the code below, from within some method that they want to force to be overridden by a subclass. In effect, they give the class 'abstract class' semantics.
This method definition acts as an abstract method, which raises an Exception if not overridden, with the following output:
-someAbstractFooMethod only defined for abstract class. Define -[YourClassName someAbstractFooMethod]!
This is an old post, but thought I'd add my experience.
@PayloW
's answer is a good answer and I think answers your question perfectly, however, no one really answered your question the other way around, so I'll do that here.Should you subclass NSMutableArray (or NSArray)? Depends on what you want to achieve. If you only want to add a method to extend an array's BASIC functionality, like sorting, then
@PayloW
's answerCategories
are the way. However, if you want to create a custom class that behaves like an array then yes, subclassingNSMutableArray
is quite easy. But because it's a Class Cluster it doesn't exactly subclass as you'd expect. Normally in subclassing the methods available in the Super Class are available to your subclass or you may override them. With Class Clusters you MUST instead include the Super's methods that you're going to use and provide a_backend
instance of the super class to wrap those methods around.Below is an example of how you'd subclass
NSMutableArray
(or any Class Cluster):The interface:
The implementation:
Then to use like so:
It all works very nicely, is clean and actually pretty cool to implement and use.
Hope it helps.
NSMutableArray
is not a concrete class, it is just the abstract superclass of a class cluster. The documentation forNSMutableArray
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 bridgedCFArray
. 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 seeNSArray
, but quite oftenNSCFArray
.As mentioned before, subclassing is not the same as extending 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:And the implementation would be:
Then use it simply as:
I have to agree with both node ninja and PeyloW because technically they have both right. Actually, that does not help me much.
Preamble: There are many arrays in code that all to one contain only one but different type of data e.g. classA, classB, classC.
Problem: I can easily mix arrays by passing wrong one to e.g. some selector because they are all NSMutableArray. There is no static check, only runtime one.
Solution - 1st try: Make subclass of NSMutableArray so compiler makes static check and warns about wrong data type.
That is good because compiler warns you even when you pass wrong type to -addObject or -objectAtIndex when you overload that ones. That is bad because you cannot instantiate NSMutableArray superclass this way.
Solution - 2nd try: Make new (proxy) class of some type e.g. NSObject as for NSMutableArray and add class member of type NSMutableArray.
This is good because you can instantiate NSMutableClass and compiler checks when you pass wrong type to -addObject or -objectAtIndex when you overload that ones.
The bad side of that is that you need to overload every selector of the NSMutableArray that you use, not only that ones that differs in class that array contains.
Conclusion: When you build some sophisticated code that has many class types in its arrays, believe me it is worth to try. Simply by doing this compiler showed me several errors that I would not recognize until I will face it in runtime. Or even worse, when end user would face it.
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 allNSMutableArrays
in your app.For comparison, here's an example I wrote a while back of implementing a custom
NSMutableArray
subclass.