tags:

views:

145

answers:

7

That's still not totally clear to me. Example:

NSArray *arr = [[NSMutableArray alloc] init];

I mean... yeah, it works. BUT: Why can I tell the compiler "hey, my var is just an NSArray, you just need to reserve space so that this fits in there" and then, in reality, there comes a big, fat NSMutableArray into that place that has way more methods, way more instance variables, and just needs way more space. I mean... how is that possible?

I would understand the other way: Big fat NSMutableArray on left side, and tiny NSArray und the right. For my understanding the superclass is always smaller, less complex then the subclass. The subclass may override some stuff, but it may add some stuff too. Right?

Imagine you buy a garage, because your wife told you on the phone she bought something that can drive. Then, it's not just a small car like you thought. She bought a big truck. And it doesn't fit in there.

So how must I think about this, to get it in my head? ;)

This goes to community wiki, just for the case others are confused too.

+5  A: 

Object size has nothing to do with it, since the assignment only assigns a reference (one may think of it as a memory address). Size of reference is fixed and independent of object size.

Rafał Dowgird
+1  A: 

In more strongly typed languages it's perfectly normal to store a pointer to a subclass object in a variable that has been declared as a pointer to the base class. However you can't then access any of the subclass's methods or member variables.

Objective-C isn't quite so strongly typed, particularly w.r.t. message calls, where (AFAICR) there's no type checking, and you get a run-time error or a no-op if the requested message can't be handled.

Alnitak
+1  A: 

You are forgetting about the type system. NSArray is a framework class, not a language primitive. There is information that is being maintained by the runtime system.

+1  A: 

You are right about the fact that the subclass will often take more space than the parent class. However this is not a problem because the subclasses aren't really stored in the array at all -- the only thing that is stored in the array are references to the actual object, which are always of the same size.

To use your analogy, imagine that you have a number of garages where your wife has her cars. Obviously the cars are of different sizes, but that does not prevent you from having a list with the number of each car (your wifes first car was labeled 1, the next 2) and where that car is currently parked (your wife has so many cars that you have to keep your own parking lots numbered). The cars have different sizes and are different models, but you can still write them all on the list and they are still all cars, so they have something in common (you can for example drive them, each get so and so many mpg).

One of the benefits of object oriented programming is that subclasses can be used in place of their superclass.

tomjen
+5  A: 

I believe the crucial point where you're mistaken is the belief that variables contain objects and the compiler reserves space for them.

In Objective-C, like in Java, a variable only contains a reference to an object - the compiler's involvement ends there. The object itself lives in a memory area known as the heap, which is maintained by the runtime.

Michael Borgwardt
+2  A: 

In your example the size of the subclass doesn’t matter because you are allocating memory for the big fat subclass on the heap, then you store the pointer to it in a pointer to a superclass.

To correct your analogy you told someone to build a garage big enough for your wife’s car. And all you do is point to where that garage is. You may be pointing to a large garage, or a small garage, it doesn’t matter to you since you’re only pointing your wife to where the garage is, someone else took care of making sure the garage is big enough.

Rossini
+2  A: 

It seems to me you are puzzled by two facets of this. One has to do with space allocation, which a number of other answers have addressed. To sum up, declaring a reference in an object-oriented system doesn't allocate space to hold an object of that type, it simply allocates space to hold a pointer.

The other issue you seem to be confused about is what typing actually means in an object-oriented system.

I would understand the other way: Big fat NSMutableArray on left side, and tiny NSArray und the right.

Think of any class as comprising two separate things: an interface, which is the set of methods and members that it exposes, and an implementation, which determines what accesses to those methods and member will actually do.

When you declare a reference to NSArray, it means that the reference will point to objects that support the same interface as NSArray. Because NSMutableArray is a subclass of NSArray, instances of NSMutableArray will always support NSArray's interface. Therefore the assignment is safe.

Conversely, if you declare a reference to NSMutableArray, it must point to objects that support the subclass's interface. Therefore, you cannot assign a pointer to an NSArray instance to that variable, because NSArray doesn't support the full interface of NSMutableArray. (In a weakly typed system, it is possible that you can do the assignment but then get a runtime error if you try to invoke a method that exists in the interface but not in the instantiated object. I don't know how strongly typed Objective C is.)

Dave Costa
Thanks! Great answer!
Thanks