1

I have a character model class which has this structure:

@interface CharacterModel : NSObject 
{
    // parent of this character
    CharacterModel *parentChar;

    // basic details
    NSString *fname, *sname, *nick;
    NSString *char_type; // categories of characters: dwarf, etc

    // health
    int health;

    // cash
    double cash;
    double graft;

    // flags
    bool is_cop, is_player, is_ai, is_playable;

    // Skills
    int skill_speed;
    int skill_stamina;
    int skill_aggr;
    int skill_another;
    int skill_somethingelse;
    // Total = 100

    // Hidden RPG skills
    int corruption;
    int greed;

    // Rep skills
    int reputation;

    // Misc. flags
    int active, picked, is_locked;
}

The problem are 2 things.

1) I would need to re-write this structure in the @property (nonotomic)... part of the .h file, and I would need to do it again for @synthesize part of the .m file

Is there a way to reduce the need to re-write stuff; can I put all this in a struct or something and then just @synthesize that?

2) The constructor will have a stupidly long function name.

I really, really do not want to be writing a constructor that has hundreds of variables/fields.

ie:

-(id)initCharacter:(NSString *)name, and every other class variable mentioned above ...

Is there are a way around this?

I was thinking of doing a NSMutableDictionary, but you would STILL need to write a constructor with every field you want somewhere.

Any help on this would be great.

Thanks

Mike Wills
  • 20,959
  • 28
  • 93
  • 149
zardon
  • 2,910
  • 6
  • 37
  • 58
  • Shouldn't a character have two parents? – JeremyP Sep 29 '10 at 16:13
  • A coupleofother observations: The flags is_cop, is_player, is_playable could be in an enum rather than three separate boolean flags. Currency is not a floating point number, use an integer type for cash or NSDecimalNumber. The attributes that add up to 100 could possibly be properties of a skills object with business logic to enforce the constraint. – JeremyP Sep 29 '10 at 16:18
  • Wow, that's a lot of info there. A character only has 1 parent (or none) - I don't know why a character would have 2 parents. I am not sure what an enum is, but I will look it up. I will use Currency as int as suggested. A skills object sounds cool, I'll have to look into it more. – zardon Sep 29 '10 at 17:29

2 Answers2

3

I really think you should take your design one step further. It is very inflexible to have explicitly defined all the skills and flags like that. Consider creating new classes called:

  • Skill
  • Attribute
  • Flag

Your character class will then have:

NSMutableArray* skills;
NSMutableArray* attributes;
NSMUtableArray* flags;

and obviously getters/setters and add/remove methods for each.

Not only will it make your class look neater but it will also save you a lot of typing.

willcodejavaforfood
  • 43,223
  • 17
  • 81
  • 111
  • I will certainly try your idea. When you say new classes do you mean having array's in the character class, or in separate classes? – zardon Sep 29 '10 at 14:25
  • If I seperate this into 2 classes -- wouldn't I still need to keep a reference in each of these classes to its relating (parent) `character`? – zardon Sep 29 '10 at 14:28
  • Your character class could have arrays holding skill objects, attribute objects, flag objects. Makes sense? :) – willcodejavaforfood Sep 29 '10 at 14:36
  • Yes, it does. Thanks for your help. I'm going to try this right now. Thanks. – zardon Sep 29 '10 at 14:43
  • No problem, if you like my answer (or any other) please don't forget to upvote it :) – willcodejavaforfood Sep 29 '10 at 14:50
  • I do not think NSMutableArray's are right for this because all you're doing is setting an object; it does not have any value associated with it; therefore I'm going to try and use NSDictionary. However, you still have some repetitive typing of key names and their values. – zardon Sep 29 '10 at 15:06
  • I really find NSDictionaries hard to understand; its really confusing where I am in the structure ` self.credentials = [[NSMutableDictionary alloc] initWithObjectsAndKeys:nil, @"name", nil];` What happens if it needs sub-dictionaries, it gets really confusing. – zardon Sep 29 '10 at 15:35
  • If I set a value for it, I can't seem to get it back `[self.credentials setValue:@"Name" forKey:@"name"]; NSEnumerator * enumerator = [self.credentials objectEnumerator]; id element; while(element = [enumerator nextObject]) { // Do your thing with the object. NSLog( @"%@", element ); }` – zardon Sep 29 '10 at 15:35
  • search for examples using NSDictionary http://stackoverflow.com/questions/3822524/tomcat-serving-static-content – willcodejavaforfood Sep 29 '10 at 15:53
  • Okay, thanks. I'll see if I can look up some tutorials on it too. – zardon Sep 29 '10 at 17:29
  • A colleague has mentioned using a Strategy design pattern and/or factory design pattern to help with this problem. I've not done design patterns before; but will look into this further. – zardon Sep 30 '10 at 12:50
  • I guess the instances of Skill, Attribute, Flag would be used in a manner that fits with the Strategy pattern. Especially if you have a Skill activeSkill property. But possibly your game wont work in a way that you choose one active skill like diablo :) – willcodejavaforfood Sep 30 '10 at 12:59
  • Yeah, I agree. I've not really taken it any further and just thought I'd like Core Data do the heavy lifting instead of me doing it. There was also the issue of "get the app done", or "do the app right". I'll look at this whole thing again sometime -- but right now, I'm going to just go with Core Data and see how that goes. – zardon Nov 05 '10 at 16:56
0

If you can use the modern Objective-C runtime (available on the iPhone and for 64 bit OS X programs) you will have to write the property definitions twice. Just write the @property and the @synthesize parts, the instance variables will be created automatically. If you need to support the old runtime you just have to write it three times, there is nothing you can do about it.

To the constructor you probably should not pass values for every property. Initialize them to some sensible default values. Note that you don’t have to do anything if the default value is 0, 0.0, nil or NULL - alloc makes sure that all ivars are initialized to zero.

If you want to set all the properties from a NSDictionary you can use key-value-coding to set them instead of doing this manually:

for (NSString *key in dictionary) {
    id value = [dictionary objectForKey: key];
    [self setValue: value forKey: key];
}
Sven
  • 22,475
  • 4
  • 52
  • 71
  • If I put a dictionary, I would still need to write a constructor with all the vars regardless of whether they are initialize to zero or not -- unless I've mis-understood what you mean. – zardon Sep 29 '10 at 14:27