myGoldChallenge. feedback? thanks :)


#1

Hi. this is my work for this gold challenge. I’d greatly appreciate any feedback/comments.

Thanks!!

BNRContainer.h:

[code]#import “BNRItem.h”

@interface BNRContainer : BNRItem
{
NSMutableArray *_containerItems;
int _totalContainerValue;
}

// Designated initializer
-(instancetype)initWithContainerName:(NSString *)cName
containerItems:(NSMutableArray *)cItems
emptyContainerValue:(int)cValue;

  • (void)setcontainerItems:(NSMutableArray *)cItems;

  • (NSMutableArray *)containerItems;

  • (int)totalContainerValue;

@end
[/code]

BNRContainer.m:

[code]#import “BNRContainer.h”

@implementation BNRContainer

-(instancetype)initWithContainerName:(NSString *)cName
containerItems:(NSMutableArray *)cItems
emptyContainerValue:(int)cValue;
{
// Call the superclass’s designated initializer
self = [super init];

// Did the superclass's designated initializer succeed?
if (self) {
    // Give the instance variables initial values
    _itemName = cName;
    _valueInDollars = cValue;
    _containerItems = cItems;
    
    // Calculate the total value and store it in _totalContainerValue
    // First, a for loop calculates the total value of the items in the container
    for (BNRItem *item in _containerItems) {
        _totalContainerValue = _totalContainerValue + item.valueInDollars;
    }
    // Then, add the value of the empty container to the total items value
    _totalContainerValue = _totalContainerValue + _valueInDollars;
}

// Return the address of the newly initialized object
return self;

}

  • (instancetype)init
    {
    return [self initWithContainerName:@"Box"
    containerItems:[[NSMutableArray alloc] init]
    emptyContainerValue:0];
    }

-(void)setcontainerItems:(NSMutableArray *)cItems
{
_containerItems = cItems;
}

  • (NSMutableArray *)containerItems
    {
    return _containerItems;
    }

  • (int)totalContainerValue
    {
    return _totalContainerValue;
    }

@end
[/code]

main.m:

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

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

@autoreleasepool {
    
    // Create a mutable array object, store its address in items variable
    NSMutableArray *items = [[NSMutableArray alloc] init];
    
    for (int i = 0; i < 10; i++) {
        BNRItem *item = [BNRItem randomItem];
        [items addObject:item];
    }
    
    // Create a container and store the items array in it.
    BNRContainer *myContainer = [[BNRContainer alloc] initWithContainerName:@"Box of Stuff"
                                                             containerItems:items
                                                        emptyContainerValue:1000];
    
    // Print the container info: name, total value, list of items
    NSLog(@"%@, worth $%d",myContainer.itemName, myContainer.totalContainerValue);
    for (BNRItem *item in myContainer.containerItems) {
        NSLog(@"%@", item);
    }
    
    // Destroy the mutable array object
    items = nil;
    
    // Destroy the container object
    myContainer = nil;
    
}
return 0;

}

[/code]


#2

After reading chapter 3, I revised my class to use properties.

I noticed that I couldn’t set the variables like before in the methods (for example: _itemName = cName;)
I had to use setter and getter methods (self.itemName = cName;).
The only exception was with my int totalContainerValue variable.

Why is that?

BNRContainer.h

[code]#import “BNRItem.h”

@interface BNRContainer : BNRItem

// Designated initializer
-(instancetype)initWithContainerName:(NSString *)cName
containerItems:(NSMutableArray *)cItems
emptyContainerValue:(int)cValue;

@property (nonatomic, copy) NSMutableArray *containerItems;
@property (nonatomic, readonly) int totalContainerValue;

@end
[/code]

BNRContainer.m (with a revision in the designated init method using the proper superclass designated initializer)

[code]#import “BNRContainer.h”

@implementation BNRContainer

-(instancetype)initWithContainerName:(NSString *)cName
containerItems:(NSMutableArray *)cItems
emptyContainerValue:(int)cValue;
{
// Call the superclass’s designated initializer
self = [super initWithItemName:@“Name"
valueInDollars:0
serialNumber:@”"];

// Did the superclass's designated initializer succeed?
if (self) {
    // Give the instance variables initial values
    self.itemName = cName;
    self.valueInDollars = cValue;
    self.containerItems = cItems;
    
    // Calculate the total value and store it in _totalContainerValue
    // First, a for loop calculates the total value of the items in the container
    for (BNRItem *item in _containerItems) {
        _totalContainerValue += item.valueInDollars;
    }
    // Then, add the value of the empty container to the total items value
    _totalContainerValue += self.valueInDollars;
}

// Return the address of the newly initialized object
return self;

}

  • (instancetype)init
    {
    return [self initWithContainerName:@"Name"
    containerItems:[[NSMutableArray alloc] init]
    emptyContainerValue:0];
    }

@end
[/code]

main.m (same as before)

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

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

@autoreleasepool {
    
    // Create a mutable array object, store its address in items variable
    NSMutableArray *items = [[NSMutableArray alloc] init];
    
    for (int i = 0; i < 10; i++) {
        BNRItem *item = [BNRItem randomItem];
        [items addObject:item];
    }
    
    // Create a container and store the items array in it.
    BNRContainer *myContainer = [[BNRContainer alloc] initWithContainerName:@"Box of Stuff"
                                                             containerItems:items
                                                        emptyContainerValue:1000];
    
    // Print the container info: name, total value, list of items
    NSLog(@"%@, worth $%d",myContainer.itemName, myContainer.totalContainerValue);
    for (BNRItem *item in myContainer.containerItems) {
        NSLog(@"%@", item);
    }
    
    // Destroy the mutable array object
    items = nil;
    
    // Destroy the container object
    myContainer = nil;
    
}
return 0;

}
[/code]


#3

[quote]I noticed that I couldn’t set the variables like before in the methods (for example: _itemName = cName;)
I had to use setter and getter methods (self.itemName = cName;).
The only exception was with my int totalContainerValue variable.

Why is that?[/quote]
Because itemName property is declared in the superclass.

By default, you can’t directly access the instance variables of a superclass from its descendants.


#4

[quote=“ibex10”][quote]
Because itemName property is declared in the superclass.

By default, you can’t directly access the instance variables of a superclass from its descendants.[/quote][/quote]

Ah, that makes sense. Thanks.

Seems that explicitly declared variables on the header’s interface will make that variable available to subclasses, but if the variable is “created” by using @property, then subclasses can’t see them.

I wonder what the best programming practices are in this case.


#5

No, the other way around.


#6

I’m confused…

If my BNRitem.h is like this

@interface BNRContainer : BNRItem { NSString *_itemName; int itemValueInDollars; }

then if I use these variables on the subclass BNRContainer’s methods, they work fine.

[code]-(instancetype)initWithContainerName:(NSString *)cName
containerItems:(NSMutableArray *)cItems
emptyContainerValue:(int)cValue;
{
// Call the superclass’s designated initializer
self = [super init];

// Did the superclass's designated initializer succeed?
if (self) {
    // Give the instance variables initial values
    _itemName = cName;
    _valueInDollars = cValue;
    _containerItems = cItems;[/code]

But when BNRItem uses properties

@property (nonatomic, copy) NSString *itemName; @property (nonatomic) int valueInDollars;

then using these ivars directly in BNRContainer cause an error, and I have to use accessor methods to get and set them.

[code]self = [super initWithItemName:@“Name"
valueInDollars:0
serialNumber:@”"];

// Did the superclass's designated initializer succeed?
if (self) {
    // Give the instance variables initial values
    self.itemName = cName;
    self.valueInDollars = cValue;

[/code]

So what is the other way around?
And thanks for helping out!