Possible Duplicate:
Why does fast enumeration not skip the NSNumbers when I specify NSStrings?
I noticed some unexpected behavior while using fast enumeration recently. In hindsight I was probably expecting fast enumeration to do more than it's intended for, so I'm looking for some clarification on how it's actually works.
Say I have a parent class Shape with 2 child classes, 3SidedShape and 4SidedShape. I have an array called myShapes, that contains objects from both the 3 and 4 sided classes.
If I wanted to search through the array myShapes, but I'm only concerned with 3 sides shapes what I was doing is:
for (3SidedShape *shape in myShapes)
My thought was that I would only be iterating over objects of class 3SidedShape, but that is not the case? I guess I'm casting all objects as 3SidedShape whether they like it or not. I'm evening returning the object after as a completely different class. Granted I'm not calling any methods that both classes don't have, but I didn't expect class siblings to just re-cast so easily without a hitch? Did I just get lucky here or can you really enumerate as any class you please regardless of relation? Can anyone explain what actually happens during enumeration?
The type specified in a for...in loop, aka fast enumeration, casts all the elements in the collection to the specified type. The reason why they are "re-cast so easily" is that casting does NOT turn one type of object into another (how would that work?). It's a hint to the compiler telling it to treat the object as if it were the other type, as if to say "don't worry, this object is of (insert type), so type check it as such." Sending the object a message it can't handle, but the type it was casted to can, will still crash the app. What you should do is this:
for (id shape in myShapes){
if ([shape isKindOfClass: [3SidedShape class]]){
//insert code here
}
}
That code assumes nothing of type, using introspection to only perform the code for objects who are of type 3SidedShape or a subclass of 3SidedShape. For exact checking (excluding subclasses) use isMemberOfClass:. Be wary of using isMemberOfClass: to test membership of a class in a class cluster (NSNumber), however, due to their more complex internal implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With