Gold challenge - solution using class methods


#1

I’m not sure if I got the task wrong or just lack of experience maybe, but my solution looks more complicated and different than other people posted in here - all because I used class methods for container array.
Here we go:

BNRContainer.h

//  BNRContainer.h
#import <Foundation/Foundation.h>
#import "BNRItem.h"

@interface BNRContainer : BNRItem

+(void) instanceCollector: (id) item;

@end

BNRContainer.m

//  BNRContainer.m
#import "BNRContainer.h"

@implementation BNRContainer

NSMutableArray *container;
int sum = 0;

+(void) instanceCollector: (id) item
{
	if (container == nil) {
		container = [[NSMutableArray alloc] initWithObjects:item, nil];
		sum = sum + [item valueInDollars];
	}
	else {
		[container addObject:item];
		sum = sum + [item valueInDollars];
	}
}

- (NSString *)description
{
	NSString *descriptionString =
	[[NSString alloc] initWithFormat:@"Container contains the following: %@, \nthe total value in dollars is: %i$",container, sum];
	
	return descriptionString;
}

@end

main.m

//  main.m

#import <Foundation/Foundation.h>
#import "BNRItem.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 array];
		
		for (int i = 0; i < 10; i++) {
            BNRItem *p = [BNRItem randomItem];
			[BNRContainer instanceCollector: p];
            [items addObject:p];
        }
		
		for (BNRItem *item in items) {
			NSLog(@"%@", item);
		}
		
		 BNRContainer *check = [[BNRContainer alloc] init];
		 NSLog(@"%@", check);
		
        items = nil;
		
	}
    return 0;
}

#2

I would make BNRContainer’s global variables (container and sum) static variables; I would also rename the method (instanceCollector) to indicate what actually it does.

//  BNRContainer.m
#import "BNRContainer.h"

@implementation BNRContainer

// ---> Make these variables static
NSMutableArray *container;
int sum = 0;

// ---> Give a new name to this method, a name that reflects what the method does
+ (void)instanceCollector:(id)item
{
   if (container == nil) {
      container = [[NSMutableArray alloc] initWithObjects:item, nil];
      sum = sum + [item valueInDollars];
   }
   else {
      [container addObject:item];
      sum = sum + [item valueInDollars];
   }
}
...
@end

Revised BNRContainer.m:

//  BNRContainer.m
#import "BNRContainer.h"

@implementation BNRContainer

static NSMutableArray *container;
static int sum = 0;

+ (void)collectItem:(id)item
{
   if (container == nil) {
      container = [[NSMutableArray alloc] initWithObjects:item, nil];
      sum = sum + [item valueInDollars];
   }
   else {
      [container addObject:item];
      sum = sum + [item valueInDollars];
   }
}
...
@end

Making global variables static restricts their visibility to the module in which they appear and thus prevents potential link-time duplicate-name conflicts.


#3

Thanks for review! Noted!
Though, do you think that my version (class methods) is a bit lame design pattern or it’s fine for now?


#4

The class method is appropriate if the intention is to have only one container for all allocated items.


#5

Basically, yes. I thought it’d be better to have this array of objects inside a class so whenever you create an instance of BNRContainer or send a message to it it gives u the whole array.