My subclass cant see the variable declared through @property


#1

The thing is, in my BNRItem.h I have my variables, but when I create my @properties at the end of the chapter and erase the variables (because they are created by the properties already), suddenly if I have a subclass of BNRItem like BNRContainer in the gold challenge in chapter 2, the subclass cant “see” the int variable for valueInDollars

main

[code]#import <Foundation/Foundation.h>
#import “BNRItem.h”
#import “BNRContainer.h”

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

@autoreleasepool {
    
    BNRItem *backpack = [[BNRItem alloc]init];
    [backpack setItemName:@"Backpack"];
    
    BNRItem *calculator = [[BNRItem alloc]init];
    [calculator setItemName:@"Calculator"];
    
    [backpack setContainedItem:calculator];
    
    backpack = nil;
    
    NSLog(@"container %@", [calculator container]);
    
    calculator = nil;
    
}
return 0;

}
[/code]

BNRItems.h

[code]
#import <Foundation/Foundation.h>

@interface BNRItem : NSObject

  • (id)randomItem;
  • (id)initItemName:(NSString *)name
    serialNumber:(NSString *)sNumber;
  • (id)initWithItemName:(NSString *)name
    valueInDollars:(int)value
    serialNumber:(NSString *)sNumber;

@property (nonatomic, strong) NSString *itemName;
@property (nonatomic, strong) NSString *serialNumber;
@property (nonatomic) int valueInDollars;
@property (nonatomic, strong, readonly) NSDate *dateCreated;

@property (nonatomic, strong) BNRItem *containedItem;
@property (nonatomic, weak) BNRItem *container;

@end[/code]

BNRItems.m

[code]
#import “BNRItem.h”

@implementation BNRItem
@synthesize itemName, container, containedItem, serialNumber, valueInDollars, dateCreated;

  • (id)randomItem
    {
    NSArray *randomAdjectiveList = [NSArray arrayWithObjects:@“Fluffy”, @“Rusty”, @“Shiny”, nil];

    NSArray *randomNounList = [NSArray arrayWithObjects:@“Bear”, @“Sporf”, @“Mac”, nil];

    NSInteger adjectiveIndex = rand() % [randomAdjectiveList count];
    NSInteger nounIndex = rand() % [randomNounList count];

    NSString *randomName = [NSString stringWithFormat:@"%@ %@",
    [randomAdjectiveList objectAtIndex:adjectiveIndex],
    [randomNounList objectAtIndex:nounIndex]];

    int randonValue = rand() % 100;

    NSString *randomSerialNumber = [NSString stringWithFormat:@"%c%c%c%c%c",
    ‘0’ + rand() % 10,
    ‘A’ + rand() % 26,
    ‘0’ + rand() % 10,
    ‘A’ + rand() % 26,
    ‘0’ + rand() % 10];

    BNRItem *newItem = [[self alloc] initWithItemName:randomName
    valueInDollars:randonValue
    serialNumber:randomSerialNumber];
    return newItem;
    }

  • (id)initWithItemName:(NSString *)name valueInDollars:(int)value serialNumber:(NSString *)sNumber
    {
    self = [super init];

    if (self){
    [self setItemName:name];
    [self setSerialNumber:sNumber];
    [self setValueInDollars:value];
    dateCreated = [[NSDate alloc]init];
    }
    return self;
    }

  • (id)initItemName:(NSString *)name serialNumber:(NSString *)sNumber
    {
    return [self initWithItemName:name
    valueInDollars:0
    serialNumber:sNumber];

}

  • (id)init
    {
    return [self initWithItemName:@“Item"
    valueInDollars:0
    serialNumber:@”"];
    }

  • (void)setContainedItem:(BNRItem *)i
    {
    containedItem = i;
    [i setContainer:self];
    }

  • (NSString *)description
    {
    NSString *descriptionString = [[NSString alloc]initWithFormat:@"%@ (%@): Worth $%d, recorded on %@",
    itemName, serialNumber, valueInDollars, dateCreated];
    return descriptionString;
    }

  • (void)dealloc
    {
    NSLog(@“destroy: %@”, self);
    }

@end[/code]

BNRContainer.h

[code]
#import “BNRItem.h”

@interface BNRContainer : BNRItem
{
NSMutableArray *subItems;
NSString *containerName;
}

  • (id)initWithContainerName:(NSString *)containerName;

  • (int)totalValue;

//necesito un setter y pq no un getter, para meter items en el array, y creo que también crear el array desde init, eso no estoy seguro

  • (void)addItemsToContainer:(NSMutableArray *)sItems;

  • (void)setSubItems:(NSMutableArray *)sItems;

  • (NSMutableArray *)subItems;

  • (void)setContainerName:(NSString *)cName;

  • (NSString *)containerName;

@end[/code]

BNRContainer.m

#import "BNRContainer.h"

@implementation BNRContainer

- (id)initWithContainerName:(NSString *)cName
{
    self = [super init];
    if (self) {
        [self setContainerName:cName];
        [self setSubItems: [[NSMutableArray alloc]init]];
    }
    return self;
}

- (id)init{
    return [self initWithContainerName:@"needs name"];
}

- (void)addItemsToContainer:(id)bItems
{
    [subItems addObject:bItems];
}


- (void)setSubItems:(NSMutableArray *)sItems
{
    subItems = sItems;
}
- (NSMutableArray *)subItems
{
    return subItems;
}
- (void)setContainerName:(NSString *)cName
{
    containerName = cName;
}
- (NSString *)containerName
{
    return containerName;
}
- (int)totalValue
{
    // y  si no hay items?
    int valueAcumulated = valueInDollars;
    for (int i = 0; i < [subItems count]; i++) {
    valueAcumulated += [[subItems objectAtIndex:i] valueInDollars];
    }
    return valueAcumulated;
    NSLog(@"%d", valueAcumulated);
}

- (NSString *)description
{
    NSString *descriptionString = [[NSString alloc]initWithFormat:@"Container: %@ with value: %d, and items detail %@",
                                   [self containerName], [self totalValue], subItems];
    return descriptionString;
    
}

@end

The error: BNRContainer.m:60:27: Use of undeclared identifier ‘valueInDollars’


#2

You are trying to access a private instance variable of the super class.

Add self to it to access the value indirectly through the property:

- (int)totalValue
{
    // y  si no hay items?
    int valueAcumulated = [self valueInDollars];
    for (int i = 0; i < [subItems count]; i++) {
    valueAcumulated += [[subItems objectAtIndex:i] valueInDollars];
    }
    return valueAcumulated;
    NSLog(@"%d", valueAcumulated);
}

Without self, you would be trying to access a private instance variable of the super class.

Compile this program to see the error message in a simpler context:

// main.m

#import <Foundation/Foundation.h>

@interface Foo: NSObject

@property int fooness;

@end

@interface FooBar: Foo

- (void)accessFoonessDirectly;
- (void)accessFoonessIndirectly;

@end

int main(int argc, const char * argv[])
{
    return 0;
}

@implementation Foo
@synthesize fooness;
@end

@implementation FooBar
- (void)accessFoonessDirectly
{
    int x = fooness;          // Not okay because fooness instance variable is private
}

- (void)accessFoonessIndirectly
{
    int x = [self fooness];   // Ok accessing through property
}
@end

#3

Great!!..thanks a lot!!