Search code examples
objective-ccocos2d-iphonesubclassing

Design complexity with subclassing in Objective-C


I'm using Cocos2D for iOS, but you most likely don't have to be familiar with Cocos2D, just Obj-C to answer my question.

I have an enemy class while developing this game that I've used for a long time, but now it's reached a point of complexity and I'll need to do something about to make it more organized and readable.

The way it works currently is this: I have the enemy class that I allocate a certain number of times and insert into a mutable array. I can then flip through that mutable array whenever. When the enemy class is allocated, it is also directed to initialize and pass a string of the enemy name. In it's init there are a series of if/if else statements that check the enemy name and set the right values for it. This worked just fine, except design-wise it got very confusing to look through all those names when I added more and more enemies.

What I want to do now is subclass off of my enemy class of all the different enemies. I'll need to access the enemy's properties just like I would other kinds of enemies from that class.

Right now in the enemy class init I have something like:

-(id) initWithEnemy:(NSString *)kind {

    if([kind isEqualToString:@"enemyName"]){

    //set values

    }
    else if([kind isEqualToString:@"anotherEnemyName"]){

    //set values

    }

    //etc, etc..

}

Now I want to have this set values stuff happen in other files. One, or a set of header/main files for each enemy. So inside initWithEnemy, I was thinking maybe I could allocate an enemy name class from the "kind" string that's passed. Not sure if I could use NSClassFromString. I've experimented with it a bit, but I'm not really sure how to access the class properties the way I did before. Even if I did access the properties the same way I did before, does that mean all the enemy name classes will have to have all the same amount of properties?


Solution

  • You can split your enemies into an abstract base class with concrete sub-classes - that is a good approach. Be mindful though, that it can often be better to use composition over inheritance - this is where you inject objects into a holder class to model something. Otherwise you might run into the problem where you have an enemy that's both a 'Monster' and a 'Wizard' and the single inheritance chain doesn't allow that.

    There are two design patterns that seem appropriate here - they both focus on decoupling complex instantiation rules from the class itself. One is the factory pattern and the other is the builder pattern. If you split into a class hierarchy the former will be appropriate, otherwise the latter.

    Sorry, can't provide more examples - writing this on an iPad, and on the way out the door.