0

How can I limit the type of objects put in an array if the limited objects are all inherited from a superclass?

So for instance, I have a parent class called

parentObj

I then have 3 child classes that have parameters that are added and not available to the superclass (parentObj)

childClass1
childClass2
childClass3

Then I have some other classes that are not related but I want to stay out of the array I'm trying to build up

otherClass1
otherClass2

I have this mutable array

NSMutableArray *arrayOfChildren;

that I want built up primarily of the three child classes of parentObj and not be able to contain the otherClasses

I don't want to build a different method to read and write the child classes to the array for each child class, because there could very well be more child classes that I build!

How can I have one method to add those classes to the array, and one to read them, including the child's added parameters?

Michael King
  • 640
  • 1
  • 6
  • 18

2 Answers2

0

The primary way I handle this problem was actually taught to me by a PHP book I was reading. Obviously PHP is not as strict as Objective C, so I had to do some changes.

I feel that this is a very useful skill to know how to do, especially for game programmers, where an array might need to carry hundreds of objects, all restricted to a certain type.

The nice thing about inheritance, is that the child classes also take on the "type" of their parent/ grandparent classes (and as far as you can go up if your tree of classes is long).

For example, if I had a method that had a parameter of type parentObj, you could put any of its children in that parameter slot and the code will run.

- (BOOL) addObjectToArray: (parentObj *) obj {
    [array addObjectToArray:obj];
    return true;
}

BOOL worked = [self addObjectToArray:childClass1];
[self addObjectToArray:childClass2];
[self addObjectToArray:childClass3];
[self addObjectToArray:otherClass1];

the code will run all the way up to the last line, in which it won't work properly. otherClass1 is not of type parentObj, so it won't work. This has successfully allowed us to limit the types of classes that the array can hold in one easy method!

Now reading the parameters from the objects is our next step to tackle. I'm sure there are other easier ways to do it, but this is how I do it.

I put a parameter in the super class (an integer) that will hold a so called ID for the child class.

parentObj.h:
//...
- (id) initWithProperties...:() :() :()... andID: (int)idType;
@property(nonatomic) int type;
//...

parentObj.m:
//...
- (id) initWithProperties...:() :() :()... andID: (int)idType {
    //...
    self.type = idType;
    //...
}
//...

childClass1.h:
//...
@property(nonatomic) int someOtherPropertyOfChild1;
//...

childClass1.m:
//...
- (id) init {
    self = [super initWithProperties... ...andID:1];
    if (self) {
    }
    return self;
}
//...

childClass2.h:
//...
@property(nonatomic) int someOtherPropertyOfChild2;
//...

childClass2.m:
//...
- (id) init {
    self = [super initWithProperties... ...andID:2];
    if (self) {
    }
    return self;
}
//...

etc...

You need to remember which ID correlates to which child class, otherwise you are bound to get errors.

So now say you had a for loop that cycled through all the objects in the array full of classes. And say we needed to print out that extra parameter in each child class, how would we do that? I will show you how.

let's assume the variable being iterated in the for loop is x.

switch([array objectAtIndex:x].type) {
    case 1:
        //remember that childClass1 is id of one
        childClass1 *CC1 = [array objectAtIndex:x];
        NSLog(@"%d", CC1.someOtherPropertyOfChild1);
        break;
//...

if the default case is called, that means that the object it is getting from the array is a parentObj object, or a child class that is not ID'd correctly.

I hope that this helps you in your troubles, and I hope it helps you understand why inheritance is important, and why you should use it!

Michael King
  • 640
  • 1
  • 6
  • 18
  • The "Objective-C-ish" way to check for a subclass object is `if ([[array objectAtIndex:x] isKindOfClass:[childClass1 class]) ...`. It is easier , safer in the case of future extensions, and makes the type identifier in the parent class obsolete. – Martin R Jul 03 '13 at 06:59
0

Create a wrapper method that you use to add objects to the array:

- (void)addObject:(id)object
{
    if ([object isKindOfClass:[parentObj class]])
    {
        [self.arrayOfChildren addObject:object];
    }
}

You could also add an isMemberOfClass check if you wanted to also exclude instances of the parentObj class itself.

Wain
  • 118,658
  • 15
  • 128
  • 151