Andrei Diaconu
Andrei Diaconu

Reputation: 651

Classes in Objective-C

I have a class named person, with two values: age and weight.Why can't I access these two values in the main function like this:

int a=[chuck age]; int b=[chuck weight];

What is the best way to do that? Using properties is the correct way?

Header file:

#import <Foundation/Foundation.h>
    @interface person : NSObject
    {
        int age;
        int weight;
    }
    -(void) print;
    -(void) setAge;
    -(void) setWeight;

@end

Implementation file:

#import "person.h"

@implementation person

-(void) print
{
    printf("Your age is %d and your weight is %d.", age, weight);
}

-(void) setAge
{
    printf("Write age: ");
    int v;
    scanf("%d", &v);
    age=v;
}

-(void) setWeight
{
    printf("Write weight: ");
    int g;
    scanf("%d", &g);
    weight=g;
}

@end

Upvotes: 0

Views: 165

Answers (3)

Mostafa Berg
Mostafa Berg

Reputation: 3239

Your problem is You're trying to access private age and weight ivars, which aren't accessible this way.

The good way to do this is to use ObjC properties, but this is not required for your example.

You need to create two methods to access the private ivars, call them age and weight, they should look like this in the class interface:

- (int) age;
- (int) weight;

and the implementation is:

- (int) age{
   return age;
}

- (int) weight{
   return weight;
}

Now in your main.m you can easily access the data needed like this:

#import <Foundation/Foundation.h>
#import "person.h"
int main(int argc, char *argV[]) {
    @autoreleasepool {
        person *andrew = [[person alloc]init];
        [andrew setAge];
        [andrew setWeight];
        NSLog(@"Age:%d, Weight:%d",[andrew age], [andrew weight]);
    }
return 0;
}

If you want to know how it's done with properties please let me know and I can update the answer :)

Upvotes: 2

bbum
bbum

Reputation: 162712

Are you working from some kind of a tutorial or book? That is an odd place to start for learning to write OS X or iOS apps.

In any case, the issue is that you've colluded getter/setter stuff with methods that implement other functionality.

I would suggest that your Person class be declared as:

 @interface Person : NSObject
 @property NSInteger age;
 @property NSInteger weight;
 @end

With Person.m:

 @implementation Person
 - (id) init {
     self = [super init];
     if (self) {
          // preposterous initial values so we know if they weren't set.
          _age = -1;
          _weight = -1; 
     }
     return self;
 }
 @end

That is, a Person only holds information about a single person. It does not do any kind of I/O, etc...

Then, your main.m would look something like:

#import <Foundation/Foundation.h>
#import "Person.h"

NSInteger ScanIntegerWithPrompt(NSString *prompt) {
    printf("%s: ", [prompt UTF8String]);
    int v;
    scanf("%d", &v);
    return (NSInteger) v;
}

int main(...) {
    @autoreleasepool {
      Person *p = [[Person alloc] init];
      p.age = ScanIntegerWithPrompt(@"Enter age:");
      p.weight = ScanIntegerWithPrompt(@"Enter weight:");
      printf("Your age is %d and your weight is %d", p.age, p.weight);
    }
    return 0;
}

Structuring the code this way separates the Model -- the data container -- from the Control layer. There isn't much of a View layer here.

If you really wanted to keep the I/O / parse logic with the Person object, then add something like this to the Person object:

...
- (NSNumber)readIntegerWithPrompt:(NSString*)prompt
{
    ... same code as function above ...
}

- (void)readAgeFromStandardInput
{
   self.age = [self readIntegerWithPrompt:@"Enter age: "];
}

- (void)readWeightFromStandardInput
{
   self.weight = [self readIntegerWithPrompt:@"Enter weight: "];
}
...

Then you'd call those methods from your main.

Upvotes: 8

kokluch
kokluch

Reputation: 602

In your header file :

@property int age;
@property int weight;

Upvotes: 0

Related Questions