Resolved Help porting a Java design pattern to Objective C

Discussion in 'Mac Programming' started by gilpster, Feb 25, 2011.

  1. gilpster, Feb 25, 2011
    Last edited: Feb 26, 2011

    gilpster macrumors newbie

    Joined:
    Feb 25, 2011
    #1
    Hi Everyone,

    I've quite a bit of experience coding in Java etc. I'm trying to port a program from Java to Objective C but i'm struggling with one aspect:

    I have a main class called 'Body' which creates instances of many other classes. Lots of theses classes inherit from a few parents classes. They all need to reference to each other, and in particular back to the 'Body' class (to which most of them belong)

    In Java I passed a refence to the class in the constructor:

    Code:
    Dog dog = new Dog(this);
    which was then stored as a pointer to the main Body class in the new class:

    Code:
    private Body body;
    
    public Dog(Body bodyRef)  {
         body = bodyRef;
         //now do things with this refence throughout the class
         body.doCoolThings();
    }
    
    And these pointers were inherited throught my OOP so I could refence this 'Body' class anywhere.

    I've tried doing the same thing with Objective C and I can't. I know i've probably got some deep misunderstanding here, but if you do this:

    Code:
    Body bodyRef = [[Body alloc] init];
    Body body = bodyRef;
    Would this just create two pointers to the same object in ObjC?

    I can't even seem to:

    #import "Body.h"

    In the interface of the other class files as it gives me an error when I compile - although I can import all my other classes.

    So how do you pass a pointer of a class to a another class in ObjC?

    Many Thanks

    Kenneth
     
  2. kainjow, Feb 25, 2011
    Last edited: Feb 25, 2011

    kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #2
    In Objective-C you run into problems when class A imports class B and class B imports class A. I imagine this is what you're seeing. To solve it you need to use @class.

    For example, the wrong way:
    Code:
    [color=#007400]// A.h[/color]
    [color=#643820]#import [/color][color=#c41a16]"B.h"[/color][color=#643820]
    [/color][color=#aa0d91]@interface[/color] A : NSObject {
        [color=#3f6e74]B[/color] *[color=#3f6e74]b[/color];
    }
    [color=#aa0d91]@end
    [/color]
    [color=#007400]// B.h[/color]
    [color=#643820]#import [/color][color=#c41a16]"A.h"[/color][color=#643820]
    [/color][color=#aa0d91]@interface[/color] B : NSObject {
        [color=#3f6e74]A[/color] *[color=#3f6e74]a[/color];
    }
    [color=#aa0d91]@end[/color]
    The right way:
    Code:
    [color=#007400]// A.h[/color]
    [color=#aa0d91]@class[/color] [color=#3f6e74]B[/color];
    [color=#aa0d91]@interface[/color] A : NSObject {
        [color=#3f6e74]B[/color] *[color=#3f6e74]b[/color];
    }
    [color=#aa0d91]@end[/color]
    [color=#007400]
    // B.h[/color]
    [color=#aa0d91]@class[/color] [color=#3f6e74]A[/color];
    [color=#aa0d91]@interface[/color] B : NSObject {
        [color=#3f6e74]A[/color] *[color=#3f6e74]a[/color];
    }
    [color=#aa0d91]@end[/color]
    Then in the implementation (.m) file, you can #import the class.

    @class basically just tells the compiler that this class name exists. It doesn't need to know anymore about it at that point.

    You should almost always use this, except when subclassing another object or conforming your object to a protocol.
     
  3. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #3
    Not sure if Body is an instance and the other objects are instantiated in instance methods, or if the other Objects are instantiated from a static/class method. If you need to pass the class, there is a Class type and you can get this by passing the message class to an object (including a class object). If you're dealing with an instance you can pass self to an init method.

    Class:
    Code:
    From body.m:
    
    Dog *myDog = [[Dog alloc] initWithParentClass:[Body class]];
    
    From Dog.h:
    ...
    Class parentClass;
    ...
    
    
    From Dog.m:
    
    (id) initWithParentClass: (Class) inClass {
      ...
      parentClass = inClass;
    }
    
    Using an instance:
    Code:
    From body.m:
    
    Dog *myDog = [[Dog alloc] initWithBody: self];
    
    From Dog.h:
    
    body *bodyRef;
    
    @property (retain) body *bodyRef;
    
    From Dog.m:
    
    (id) initWithBody: (body *) inBody {
      ...
      [self setBodyRef:inBody];
      ...
    }
    
    Hopefully one of these is what your looking for, and the very short examples help. If not, post again.

    -Lee
     
  4. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #4
    In Objective-C, you can send messages to classes and to objects. For example:

    Code:
    NSArray* anArray = [[NSArray alloc] init];
    int count = [anArray count];
    
    sends the alloc message to class NSArray, which returns an object, then sends the init message to that object, and the count message to the object returned. To get a class object, send the "class" method:

    Code:
    Class someClass = [NSArray class];
    NSArray* anArray = [[someClass alloc] init]
    will do exactly the same thing.
     
  5. gilpster thread starter macrumors newbie

    Joined:
    Feb 25, 2011
    #5
    Thanks guys - your answers have sorted this problem out for me I think:

    @lee1210, gnasher - I wanted to pass an instance of the class rather than the class itself.

    @kainjow - using the

    Code:
    @class foo;
    in the interface solved the problem. I think you hit the nail on the head. A better way to define my problem would be if you had three classes, A, B and C. Supposing an instance of A creates instances of classes B and C. Then what would you do if you wanted to access the instance of class C from class B? I think you'd do it this way:

    Code:
    // B.h
    @class A;
    @interface B : NSObject {
        A *a;
    }
    @property(nonatomic, retain) A * a;
    -(void) getReferenceFromA: (A *)aRef;
    -(void) usingCfunction;
    @end
    
    // B.m
    #import "A.h"
    @implementation B
    @synthetize a;
    
    -(void) getReferenceFromA: (A *)aRef  {
        a = aRef;
    }
    
    -(void) usingCfuntion {
       [a.c setSomething];  //assuming that the instance of C is 'c'
    }
    @end
    if this is right - and it seems to work in Xcode here - i'll mark the thread solved - (but I don't know how)

    kenneth
     
  6. elppa macrumors 68040

    elppa

    Joined:
    Nov 26, 2003
    #6
    Just edit the title and put [solved] at the front. That should do. There is no formal way.
     
  7. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #7
    We recently added a Resolved prefix which is the preferred way to do this.
     
  8. elppa macrumors 68040

    elppa

    Joined:
    Nov 26, 2003
    #8
    Silly me.
     

Share This Page