Singleton / BRMItemStore correct?


#1

Hi,
I just studied the singleton chapter and fell across the following question:

in the core of the recipe the sharedStore is allocated:

But wil this allocate the space on the heap which is needed for the ivars (pointer to an NSArray in this case)?
Shouldn*t it read something like

Thanks in advance
Thomas


#2

To answer your question, it WILL allocate space on the heap for your array instance variable. The reason you’re not doing this:

sharedStore = [BNRItemStore allocWithZone:nil] init];

is because you overrode BNRItemStore’s +allocWithZone: like so:

return [self sharedStore];

Therefore, using BNRItemStore as the receiver above would create an infinite loop of calls to +allocWithZone: then to +sharedStore and back to +allocWithZone:…


#3

I understood the problem with the loop.
But: What does this exactly do?

I thought “super” refers die the superclass (of BMRItemStore). If the space for the super class is allocated it does not have the space for the additional ivars of self. Am I wrong here already? I am confused.

Thanks
Thomas


#4

super and self refer to the same instance, the receiver of the message. They differ in which method is selected. [self someMethod] uses the definition of someMethod in the receiver’s class. [super someMethod] starts searching for someMethod in the superclass of self. If it is not found in the superclass it continues up the inheritance hierarchy. Using super in this case allocates memory for the BNRItemStore instance using the +allocWithZone: method of the superclass, which in this case is NSObject. So you are allocating enough memory for a BNRItemStore instance, but instead are using NSObject’s implementation of +allocWithZone:


#5

Thanks for your patience @brianpalma.

I have to accept it but still I did not fully understand it: I can’t understand why super and self do mean the same in this context.

I thought [AnyClass alloc] means something like “hey, allocate memory which accommodates an AnyClass object and give me the pointer to it”.
In my thinking [[AnyClass super] alloc] would mean “allocate memory which accommodates for the super class of AnyClass” (which would be less memory if AnyClass has ivars).

But maybe the decision about the actual size of the block of memory NSAllocateObject() is finally allocating somes from another source and is not visibly dependent from the class I send this class method to.

I also read the paragraph from the book a couple of times, but still can not wrap my head around it.
“We can skip over our alloc trap within the implementation of BMRItemStore because the super keyword is only relevant to the class in which the method is implemented”.

Thanks again
Thomas


#6

Thomas,

No need to thank me for my patience! Trust me, I’ve been in your shoes not too long ago and it is rough. I hate not understanding things and then having to carry on until it clicks. Try this explanation out though. When you see something like this:

know that “super” is merely a synonym for the class of the instance receiving the message. In our case, we sent a message to the BNRItemStore class. In addition to being a synonym, super also instructs our class (BNRItemStore in this case) which method implementation to select. We (BNRItemStore) were sent the message +sharedStore whose implementation allocates an instance of BNRItemStore class using our superclass’s +allocWithZone: implementation.

You are right in thinking that [AnyClass alloc] means allocate memory and return a pointer to an instance of AnyClass. It is no different with super. super is AnyClass. What is different is that you aren’t using AnyClass’s +alloc method. Rather you are using the superclass’s +alloc to allocate an instance of AnyClass.

[AnyClass super] alloc] is wrong. Intuitively, you may think that super returns the superclass of the AnyClass class but that’s not the case. The keyword super can only be used as the receiver of a message. As said above, super IS self. They are pointers to the same object. They differ in which method implementation is selected for the message received. A message with self as the receiver looks for a method in the receiver’s class with the same signature. A message with super as the receiver looks for a method in self’s superclass with the same signature. If one isn’t found in the immediate superclass, the search continues up the inheritance hierarchy.

Using BNRItem as an example, if we overrode the -isEqual: method (-isEqual: is a method in a category on NSObject) like so:

-(BOOL)isEqual:(id)anObject
{
    [super isEqual];
}

we will be comparing two BNRItem instances using the -isEqual: implementation of our superclass (NSObject). The receiver and argument (presumably) will BOTH be BNRItem instances. NSObject’s implementation only compares the pointer values, so this implementation is not adequate. It merely is to reiterate the distinct method selection of self and super.

The takeaway is that self and super ARE the same instance. The only difference is where the search for method selection begins, the class of the receiver (self) or the superclass of the receiver (super).

As an aside, this is no different when you override an -init method. You typically assign self (an implicit local variable that points to the receiver of the message) to the returned pointer of [super init]; By doing this:

- (id)init
{
    self = [super init];
   
    if (self){
 // initialization here

}
return self;

}

You are initializing the instance returned from +alloc but using your superclass’s designated initializer (in this case, plain init) subsequently followed by class specific initialization. Since we are overriding -init we need a way to initialize our inherited instance variables AND do so without a loop (This is why it is not [self init]:wink: We assign self to this returned instance and then continue our custom initialization.

Hope this helps a bit. If not, reply and we’ll get it straightened out.

Best,

Brian


#7

A metaphor is usually used for super- and sub- classes relationship.

As NSObject is the superclass of BNRItemStore, let me use CAR to replace NSObject, and ToyotaCAR to replace BNRItemStore. CAR here means a car manufacturer.

A method - makeCar is declared in CAR, as ToyotaCAR is a subclass of CAR so it inherits makeCar method from CAR.
The context of makeCar doesn’t change from inheritance, so [CAR makeCar] is equivalent to [ToyotaCAR makeCar]. That is they produce the same instance - a car.

Similarly for super and self, which in turns meaning NSObject and BNRItemStore respectively.