Reputation: 1915
I am slowly but surely working through Apple's dense documentation, but I really have to ask a question. The following example code is given:
#import "MonthArray.h"
@implementation MonthArray
static MonthArray *sharedMonthArray = nil;
static NSString *months[] = { @"January", @"February", @"March",
@"April", @"May", @"June", @"July", @"August", @"September",
@"October", @"November", @"December" };
+ monthArray
{
if (!sharedMonthArray) {
sharedMonthArray = [[MonthArray alloc] init];
}
return sharedMonthArray;
}
- (unsigned)count
{
return 12;
}
- objectAtIndex:(unsigned)index
{
if (index >= [self count])
[NSException raise:NSRangeException format:@"***%s: index
(%d) beyond bounds (%d)", sel_getName(_cmd), index,
[self count] - 1];
else
return months[index];
}
@end
Here are my questions (I apologize for not making multiple threads, but from what I can tell - these are fairly basic.)
What exactly does it mean when it shows +monthArray? I know that the + means that it is a class method, but I don't entirely understand what implications that has. How exactly does it make it different than a normal method?
What is the purpose in this code for the whole sharedMonthArray ivar? I mean, the objectAtIndex: method is pulling from the months' strings, so what's the point?
What is the "self" in the [self count] method? I mean, I understand that it is supposed to be the months, but where do I see that in the program? What makes [self count] count the months and not count the number of MonthArrays?
Sorry if my questions are uber-elementary, I am still learning - thanks in advance for the help.
Upvotes: 1
Views: 127
Reputation: 4698
First, the class-method is missing a return type — let's fix that:
+ (MonthArray *)monthArray {...}
Now to your first question:
The difference between an instance-method and a class-method is the target, you call it on. Like the name implies, you call a class-method on the class-object. Examples of this are
// call a factory-method of NSArray to create a new array:
NSArray *array = [NSArray arrayWithObject:@"foo"];
// obtain the current notification-center
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
// obtain a singleton
NSApplication *app = [NSApplication sharedApplication];
So there is exactly one object, you can call the method on — in this case, to retrieve the singleton, that is implemented by this class.
With that we come to your second question:
When you call [MonthArray monthArray]
, you will be returned the only instance of this class that was intended to be created. There must — however — be a way to store that instance somewhere, so that it can be retrieved later. You do this in a static
variable (in Java, this would be a class variable). Same goes for the months, which are only needed once.
objectAtIndex:
only exists to wrap the raw C-array with a thin Objective-C layer. Remember, that C will happily let you do something like months[42]
— only to crash somewhere later because it's pretty unlikely that the thing you'll obtain there, will be an NSString.
Your third question:
self
is not the months! It is an instance of MonthsArray
and — as this code obviously intends — the only one that should exist (namely, the object stored as sharedMonthsArray
). As an instance of MonthArray
, it responds to the count
selector and will simply return 12 when being sent this message (see implementation of -(unsigned)count
). It doesn't count the months: you could change months like this
NSString *months[] = { @"January", @"February", @"March",
@"April", @"May", @"June", @"July", @"August", @"September",
@"October", @"November", @"December", @"Dancing Hippo Month" };
and it would still return 12.
Upvotes: 0
Reputation: 119154
What exactly does it mean when it shows +monthArray? I know that the + means that it is a class method, but I don't entirely understand what implications that has. How exactly does it make it different than a normal method?
Class methods are functions that can be called without providing an instance of the class. In Objective-C, you normally send messages to an instance as follows: [someObject someMethod];
With a class method, you send the message to the class itself: [SomeClass someClassMethod];
. Class methods are usually used to do things that are specific to all objects of that particular class, such as creating a new instance (i.e. a factory method) or maintaining/updating a global class variable.
What is the purpose in this code for the whole sharedMonthArray ivar? I mean, the objectAtIndex: method is pulling from the months' strings, so what's the point?
The purpose of sharedMonthArray
is to hold a single, common instance of the class. It would be possible to return a new instance every time +monthArray
is called, but that could be a waste of memory, since there really only needs to be one. Most Cocoa code uses NSArray
objects, and not simple C-style arrays, so this single instance is like a NSArray
wrapper to hide that static C-array from the rest of the program by providing a NSArray
instance instead. Internally, the C-style array is used because there is no way to create a static constant NSArray
object at compile-time.
What is the "self" in the [self count] method? I mean, I understand that it is supposed to be the months, but where do I see that in the program? What makes [self count] count the months and not count the number of MonthArrays?
self
is an automatic variable that the Objective-C runtime uses to hold the object which receives a certain message. If you send the message [someObject someMethod];
, this will jump to the -someMethod
method, and the value of self
will be equal to someObject
. In this example, self
will be whichever instance of MonthArray
was sent the -objectAtIndex:
message. The call to [self count]
will result in the method -count
being called, and will return a value of 12, according to the code shown.
I would like to add that the code shown here is fairly unique in the Cocoa world. The only time you would really write something like this is if you were creating your own framework. The majority of Cocoa source code will not use C-style arrays. What was the purpose of this particular example? It is definitely not the kind of code a Cocoa developer will write on a daily basis.
Upvotes: 4
Reputation: 5765
This object is implemented as a singleton, meaning that in normal use there will only be one instance. You get a reference to that instance with [MonthArray monthArray]
, which sends the message +monthArray
to the class MonthArray
. That method creates the sharedMonthArray
if needed, and returns it. Since sharedMonthArray
is declared static
, it isn't an instance variable - it's a class variable, shared by all instances and accessible to class methods.
-count
is simply a message that can be sent to a MonthArray
, and it always returns 12, which is the number of months in a year. That message doesn't do any real work. It's more of a getter for a property that isn't explicitly declared.
The occurrences of [self count]
are where the MonthArray
instance sends a message to itself. In other languages, it might be written as this.count()
Upvotes: 1