Typdef enum in constructor?

Discussion in 'Mac Programming' started by magda1986, Mar 17, 2011.

  1. magda1986 macrumors newbie

    magda1986

    Joined:
    Mar 5, 2011
    #1
    Hello,

    I need help to properly write my model: I want to define a body, made of body parts.
    rem: Not being an IT person, I may go a wrong direction ;)

    I guess that creating one subclass per body part is just wrong. There's so much of them - moreover the subclasses wouldn't have an added value (no specific behavior needed).

    I read about "typedef enum", which allows me to list "constants". I'm trying to use this with a custom "constructor":

    Code:
    #imports (...)
    
    typedef enum bodyParts {
    HEAD, HAND_LEFT, THUMB_LEFT, FINGER2_LEFT, (...), LUNG_LEFT, (...)
    } bodyParts;
    
    
    @interface BodyPart : NSObject {
     BodyPart *parentBodyPart;
     (...)
    }
    [INDENT]- (BodyPart*) initWithType:(???)part;[/INDENT]
    @end
    However, I've not found how to pass an item from my typedef at construct time.
    I read on forums to "use the language, don't fight with it". Maybe my approach is just wrong.

    Please help and provide me with some guidance!
     
  2. Hansr macrumors 6502a

    Joined:
    Apr 1, 2007
    #2
    How are you planning on using this in your program? Maybe a class may be more applicable.
     
  3. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #3
    Some kind of init message is the Objective-C analogy to a constructor.

    You could declare instance variables, properties and a set of init message like this in your interface:

    Code:
    @interface BodyPart : NSObject {
      BodyPart *parentBodyPart;
      bodyParts bodyPart;
    }
    
    @property (assign) bodyParts bodyPart;
    @property (retain) BodyPart *parentBodyPart;
    
    - (id)initWithBodyPart:(bodyParts)aBodyPart;
    
    /* Designated initialiser */
    - (id)initWithBodyPart:(bodyParts)aBodyPart 
            parentBodyPart:(BodyPart *)aParentBodyPart;
    
    @end
    
    And implement the messages and synthesise your properties in the implementation like so:

    Code:
    @implementation BodyPart
    
    @synthesize bodyPart;
    @synthesize parentBodyPart;
    
    - (id)initWithBodyPart:(bodyParts)aBodyPart {
      return [self initWithBodyPart:aBodyPart
                     parentBodyPart:nil];
    }
    
    - (id)initWithBodyPart:(bodyParts)aBodyPart
            parentBodyPart:(BodyPart *)aParentBodyPart {
      self = [super init];
      if (self) {
        self.bodyPart = aBodyPart;
        self.parentBodyPart = aParentBodyPart;
      }
      return self;
    }
    
    @end
    
    Then you can allocate and initialize a BodyPart object using something this:

    Code:
    BodyPart *aLeftHand = [[BodyPart alloc] initWithBodyPart:LEFT_HAND];
    BodyPart *aLeftThumb = 
      [[BodyPart alloc] 
          initWithBodyPart:LEFT_THUMB 
            parentBodyPart:aLeftHand];
    
     
  4. magda1986 thread starter macrumors newbie

    magda1986

    Joined:
    Mar 5, 2011
    #4
    Jiminaus, that looks wonderful! I'm impatient to get back home and try this :)

    Hansr,
    Do you mean creating a subclass for each body part?
    I thought of doing that, but as no specific behavior needs to be associated with the parts, I thought creating all those subclasses wouldn't be good. They just need a way to be identified. I thought of a "switch case" to perform processing based on the selected part.

    Thanks for your time!
     
  5. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #5
    Normally a switch based on a object's property that indicates some kind of type is a good smell that you do need to create subclasses and break the parts of the switch into the subclasses.

    For example instead of this smelly code:

    Code:
    - (void)drawBodyPart:(BodyPart* )aBodyPart {
      switch (aBodyPart.bodyPart) {
        case HEAD:
          /* code to draw a head */
          break;
        case HAND_LEFT:
          /* code to draw a left hand */
          break;
        /* etc... */
      }
    }
    
    It's better to do declare a draw message in BodyPart and have specialised implementations in BodyPart subclasses to draw the particular body part. For example (ignoring the MVC pattern):

    Code:
    @interface BodyPart : NSObject {
    }
    - (void)draw;
    @end
    
    @interface Head : BodyPart {
    }
    @end
    
    @implementation Head
    - (void)draw {
      /* code to draw a head */
    }
    @end
    
    @interface LeftHand : BodyPart {
    }
    @end
    
    @implementation LeftHand
    - (void)draw {
      /* code to draw a left hand */
    }
    @end
    
    
    Then you can send a draw message to any BodyPart (-subclass) object it will draw the correct body part.

    NB: None of the code I've posted in this thread as been tested and may contain errors.
     
  6. magda1986 thread starter macrumors newbie

    magda1986

    Joined:
    Mar 5, 2011
    #6
    Thanks for your suggestion!
    I'll digest all that and practice as you described :D
     
  7. Sander macrumors 6502

    Joined:
    Apr 24, 2008
    #7
    Hansr asked a very important question. What are you designing this for..? Is this an "exercise" in object-oriented decomposition?

    Normally, you use inheritance because your derived object has "specifics" but may always be used where an object of the type it derives from is expected. For example, you have a function

    Code:
    PressButton(Finger* f);
    then you could pass an IndexFinger which derives from Finger.

    There is probably not much use in all body parts deriving from a generic BodyPart super class. Object hierarchies with super general classes are often a sign of overdoing OO-thinking. Is there really a function which can be performed with any BodyPart?

    The object hierarchy can also be used to create overview. You can learn the "is-a" and "has-a" relationships quite well from this example, as you could have a Torso class somewhat like this:

    Code:
    class Torso
    {
        Head* head;
        Arm* leftArm;
        Arm* rightArm;
        Leg* leftLeg;
        Leg* rightLeg;
    };
    and work your way down from there. Note that there is no LeftLeg class - the left and right legs are both of type Leg.

    Again, letting us know what you are trying to accomplish would help us provide better advice.
     
  8. magda1986 thread starter macrumors newbie

    magda1986

    Joined:
    Mar 5, 2011
    #8
    This to experiment with the idea of making a "memo" application to store topics / summaries from my courses, with a quick interface based on a "tap enabled" body map. But don't take me wrong, not a big ambitious tool :p

    Thanks for the OO explanations!

    I've tried your suggestions yesterday night. I guess I'll keep going that way!
     

Share This Page