0

I'm programming on Objective C for the first time, coming from C++ (so far I like the latter much better!). I have a question regarding mutable arrays, namely I want to create one with the specific type of one of my objects, 'CMParticle', instead of the generic ID type. To access data in my object from my mutable array, I have to cast it as one of my objects each time (which is I believe cumbersome) like so:

rij[0] = ((CMParticle *)particles[*pi]).crds[0] - ((CMParticle *)particles[*pj]).crds[0];

where 'particles' is my mutable array of CMParticle objects. I would rather do this

rij[0] = particles[*pi].crds[0] - particles[*pj].crds[0];

Prior to this I declare my mutable array like so:

particles = [NSMutableArray array];

It would be nice if I could declare this array with my type somehow so I don't have to typecast every time. Is there a way to do this?

Gavin Miller
  • 43,168
  • 21
  • 122
  • 188
jdeckman
  • 119
  • 10

1 Answers1

1

What you're trying to do doesn't actually make sense in Objective C.

C++ containers are homogenous, but generic. You can have a vector<CMParticle>, or a vector<int>, and they're different types.

ObjC containers are heterogeneous. You just have an NSArray, and it can hold CMParticle objects, NSNumber objects, or anything else, all mixed up in one big array.

You generally don't need these casts at all. If you want to send a message to my_array[3], just do [my_array[3] doSomething:15]. Just like a higher-level language (Python, Ruby, Smalltalk, Javascript, etc.).

The only problem is that (unlike Python, etc.), there are a few cases where you do need the cast. Most critically (and annoyingly), if you want to access members directly, you have to cast first. This is one of the reasons that ObjC (unlike Python, etc.) encourages you to use @property and/or explicit accessors instead of directly accessing members. (Also, as a more minor annoyance, because variables have declared types, you can't just write tempval = my_array[3];, you have to specify the type, like: CMParticle *tempval = my_array[3].)

Another way to look at this: C++ extends C's static, weak type system to give you a stronger static type system; ObjC instead bolts on a separate dynamic type system (unfortunately leaving the existing C stuff unchanged, which is where the occasional problems come in).

You can pretty easily write your own NSMutableArray subclass that's generic (taking the class at runtime, unlike C++'s compile time, of course) and homogenous, but all that does is add restrictions; the elements will still be id everywhere. The only way around that is to write a custom class for each array: MutableCMParticleArray, MutableNSNumberArray, etc.

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • What? You shouldn't need to typecast an assignment from an array element to a variable. Is this an issue with the indexed accessor syntax? Because I've been writing equivalent code with `objectAtIndex:` for years and have never needed to cast. – Chuck Apr 22 '13 at 21:52
  • @Chuck: Sorry, I put that part very misleadingly. Let me fix it. – abarnert Apr 22 '13 at 22:02
  • `objectAtIndex:` and `objectAtIndexedSubscript:` both return an `id`, so you don't need a typecast, the declaration will effect the cast. `id` is the bottom class, for the purposes of type checking all types are `id` and an `id` responds to all messages. – iluvcapra Apr 22 '13 at 22:04
  • @iluvcapra: The answer already explains that. See the paragraph "You generally…" If you want to send a message to `my_array[3]` (or `[my_array objectAtIndex:3]`), just send a message to it. I didn't want to explain the mechanism behind that working, because it gets a bit complicated (`id` isn't _really_ a root type—for one thing, it's a _pointer_ to a root type, and, for another, you can often use `id` with things that aren't subclasses of the root type), and I don't think the OP needs to understand that part. – abarnert Apr 22 '13 at 22:08
  • Yeah, it's important to understand that Objective-C is "duck-typed" -- the assignment of a pointer value to a pointer location is only loosely checked -- so you usually can get away without explicit casts. Whether this is good or bad is a matter we won't go into here. – Hot Licks Apr 22 '13 at 22:51
  • @HotLicks: This isn't really about duck typing (it doesn't matter what type something is, so long as it responds to the right messages); it's about dynamic typing (it doesn't matter what type a _variable_ is, just what type the _value_ is). Of course ObjC is _both_ (if not quite pure at either one). – abarnert Apr 23 '13 at 00:10
  • @abarnert - Yeah, it's hard to tell what type of typing Objective-C has. It's just that type of language. But, from a practical standpoint, you can assign from `id` to an object pointer type without being "diagnosed" by the compiler, and that's the type of thing that makes it all work. Or something of that type. – Hot Licks Apr 23 '13 at 00:56