1

I am practicing inheritance in Objective-C and this is my Person parent class

// This is Person.h
@interface Person : NSObject

@property(nonatomic, strong) NSNumber *age;
@property(nonatomic, strong) NSString *race;

-(instancetype)init;
-(instancetype)initWithAge:(NSNumber*)age andRace:(NSString*)race;

@end

This is what I'm trying to do in my Student class

// This is Student.h
#import "Person.h"

@interface Student : Person

@property(nonatomic, strong) NSString *classification;
@property(nonatomic, strong) NSString *major;

@end

And

// This is Student.m
#import "Student.h"
#import "Person.h"

@implementation Student

-(instancetype)init
{   
    return [self initWithClassification:@"Freshman" andMajor:@"Computer Science"
                                 andAge:[[NSNumber alloc] initWithInt:20] andRace:@"Caucasian"];
}

-(instancetype)initWithClassification:(NSString*)classification andMajor:(NSString*)major
                               andAge:(NSNumber*)age andRace:(NSString*)race
{
    self = [super init];

if (self)
{
    _classification = classification;
    _major = major;
    _age = age;
    _race = race;
}

return self;
}

@end

The compiler is not liking my doing _age = age; _race = race;

Use of undeclared identifier _age did you mean age? Can someone tell me where I went wrong? Thank you.

FoxMcWeezer
  • 113
  • 1
  • 7
  • Subclasses should avoid initializing inherited instance variables. That should be left up to the superclass initialization code, which is why your initializer methods should always call `[super init...]`. – jlehr Sep 16 '14 at 20:29

3 Answers3

3

When you declare a property like that, clang will automatically @synthesize it for you (i.e it will create a getter and setter), but synthesized properties are not visible to subclasses, you have different alternatives to make it working.

You can synthesize the ivar in the interface of the subclass

@synthesize age = _age;

Or you can declare the ivar protected on the interface of the superclass, so that will be visible on the subclasses.

@interface Person : NSObject {
    @protected NSNumber *_age;
}

Or you can use self.age = ... on your subclass, without using the ivar at all.

Daniele
  • 2,461
  • 21
  • 16
1

Since clang compiler now auto-synthesise properties you don't have, in most cases, to synthesise your properties.

Objective-C Autosynthesis of Properties

Clang provides support for autosynthesis of declared properties. Using this feature, clang provides default synthesis of those properties not declared @dynamic and not having user provided backing getter and setter methods. __has_feature(objc_default_synthesize_properties) checks for availability of this feature in version of clang being used.

But in some cases (some examples are in this question) you should explicitly synthesise them.

In this case, to solve your problems you should just add:

@synthesize age = _age;
@synthesize race = _race;

to your code, and you'll be fine.

Community
  • 1
  • 1
jMelnik
  • 1,055
  • 2
  • 15
  • 26
0

The subclass has access to the property, but not the backing variable. So you should set it with

self.age = age;
Michael Chinen
  • 17,737
  • 5
  • 33
  • 45