views:

72

answers:

2

I am a little confused about how I "set" and "get" the instance variables for an object that is contained within another. As you can see from the code below I first create a RocketBody which includes a SolidRocketMotor object. I am creating the SolidRocketMotor in RocketBody init and deallocating it in RocketBody dealloc.

My question is how would I go about setting / getting the engine (SolidRocketMotor) instance variables from within main (e.g. setting engCase)?

int main (int argc, const char * argv[]) {
    RocketBody *ares_1x;

    ares_1x = [[RocketBody alloc] init];
    [ares_1x setFuel: [NSNumber numberWithInt:50000]];
    [ares_1x setWeight:[NSNumber numberWithFloat:1.8]];
    // How to set engCase to "Standard" here?
...

.

@interface SolidRocketMotor : NSObject
{
    NSString *engCase;        
    NSString *engPropellant;  
    NSNumber *engIgniter;    
    NSString *engNozzle;      
}
@property(copy) NSString *engCase;
@property(copy) NSString *engPropellant;
@property(copy) NSNumber *engIgniter;
@property(copy) NSString *engNozzle;
@end

@interface RocketBody : NSObject
{
    NSNumber *fuel;
    NSNumber *weight;
    BOOL holdDownBolt_01;
    BOOL holdDownBolt_02;
    BOOL holdDownBolt_03;
    BOOL holdDownBolt_04;
    SolidRocketMotor *engine;
}
@property(copy) NSNumber *fuel;
@property(copy) NSNumber *weight;
@property BOOL holdDownBolt_01;
@property BOOL holdDownBolt_02;
@property BOOL holdDownBolt_03;
@property BOOL holdDownBolt_04;
@end

// ------------------------------------------------------------------- **
// IMPLEMENTATION
// ------------------------------------------------------------------- **

@implementation SolidRocketMotor
- (id) init {
    self = [super init];
    if (self) NSLog(@"_init: %@", NSStringFromClass([self class]));
    return self;
}

@synthesize engCase;
@synthesize engPropellant;
@synthesize engIgniter;
@synthesize engNozzle;

- (void) dealloc {
    NSLog(@"_deal: %@", NSStringFromClass([self class]));
    [super dealloc];
}
@end

// ------------------------------------------------------------------- **

@implementation RocketBody
- (id) init {
    self = [super init];
    if (self) {
     engine = [[SolidRocketMotor alloc] init];
     NSLog(@"_init: %@", NSStringFromClass([self class]));
    }
    return self;
}

@synthesize fuel;
@synthesize weight;
@synthesize holdDownBolt_01;
@synthesize holdDownBolt_02;
@synthesize holdDownBolt_03;
@synthesize holdDownBolt_04;

- (void) dealloc {
    NSLog(@"_deal: %@", NSStringFromClass([self class]));
    [engine release], engine = nil;
    [super dealloc];
}
@end

many thanks

gary

+2  A: 

supposing you have something like and that you declare a property setting for SolidRocketMotor *engine:

RocketBody *rb = [[RocketBody alloc] init];

Then you would do this:

SolidRocketMotor *srm = [[SolidRocketMotor alloc] init];

rb.engine = srm;

and

rb.engine.engCase = whatever;
ennuikiller
Maybe I just have the logic wrong, the problem right now is that the engine [SolidRocketMotor] is assigned/allocated in the init, so I don't (as far as I can see) have access to engine from main(); Maybe allocating the [SolidRocketMotor] within the [RocketBody init] is not the right thing to be doing?
fuzzygoat
This only works if engine is a property in RocketBody, which it isn't in the OP's code.
Ole Begemann
@Ole, yes READ MY FIRST LINE!!!
ennuikiller
I apologize. I indeed overlooked your first sentence. And so did the OP apparently.
Ole Begemann
I voted ennuikiller up as I think his answer was helpful, but just not as clearly stated as yours @Ole which I marked as accepted, thank you both.
fuzzygoat
+1  A: 

You need to provide an accessor for engine in your RocketBody class. Like this:

@interface RocketBody : NSObject
{
    // ...
    SolidRocketMotor *engine;
}
// ...
@property(retain) SolidRocketMotor *engine;
@end

@implementation RocketBody
// ...
@synthesize engine;
// ...
@end

With this, external code can access the engine property:

// Obj-C 2.0 Property style:
ares_1x.engine.engCase = @"Standard";

// or setter/getter method style:
[[ares_1x engine] setEngCase:@"Standard"];
Ole Begemann
Ole, can I ask you where you would alloc/init I am a little worried that this allows direct access to the engine, without going the ares_1x route that you so helpfully mention?
fuzzygoat
I think I got it, I went back to allocating the engine in the [RocketBody init] and deallocating it in the [RocketBody dealloc] which feels better as its hidden away in the rocket once again ...
fuzzygoat
Yes, that's right, the rest of your code should remain as it was.
Ole Begemann