This is code from an addition calculator that does operations by entering the two operands first and then the operation; like “5 enter 2 enter +” would result in “7”. When the user taps on a number a double will be sent to pushOperand: When a user taps on the addition button the string @"+" will be sent like to performOperation:. My question is what is the point of making those copies in program and runProgram: if they’re all shallow copies and their elements all end up pointing to the same elements of NSNumber and NSString objects as _programStack, program, and stack?
#import <Foundation/Foundation.h>
@interface CalculatorBrain : NSObject
@property (nonatomic, readonly) id program;
+(double)runProgram:(id)program;
-(double)performOperation:(NSString *)operation;
@end
#import "CalculatorBrain.h"
@interface CalculatorBrain ()
@property (nonatomic, strong) NSMutableArray *programStack;
@end
@implementation CalculatorBrain
@synthesize programStack = _programStack;
-(NSMutableArray *) programStack {
if (!_programStack)
_programStack = [[NSMutableArray alloc] init];
return _programStack;
}
-(void)pushOperand:(double)operand {
[self.programStack addObject: [NSNumber numberWithDouble: operand]];
}
-(double)performOperation:(NSString *)operation {
[self.programStack addObject: operation];
double result = [CalculatorBrain runProgram: self.program];
return result;
}
-(id)program {
return [self.programStack copy];
}
+(double)runProgram:(id)program {
NSMutableArray *stack;
if ([program isKindOfClass: [NSArray class]])
stack = [program mutableCopy];
return [self popOperandOffProgramStack: stack];
}
+(double)popOperandOffProgramStack:(NSMutableArray *)stack {
double result = 0;
id topOfStack = [stack lastObject];
if (topOfStack)
[stack removeLastObject];
if ([topOfStack isMemberOfClass: [NSNumber class]])
result = [topOfStack doubleValue];
if ([topOfStack isKindOfClass: [NSString class]]) {
NSString *operation = topOfStack;
if ([operation isEqualToString: @"+"]) {
result = [self popOperandOffProgramStack: stack] + [self popOperandOffProgramStack: stack];
}
return result;
}
@end
NSNumberandNSStringare immutable so making a shallow copy of a collection of objects that can’t changee is safe.In
programit is important to return a copy ofprogramStackrather than the the actual mutable array. This is becauseprogramStackis a private internal property declared in a class extension so it is not externally visible. If you returnedprogramStackdirectly an external user could change it since it is anNSMutableArray. Theprogrammethod returns anNSArraysince copies of mutable objects are immutable, which has the right semantics. You want to give the external user a snapshot of theprogramStackarray, not access to your class internals.In
runProgramthe situation is different. The external user passesCalculatorBrainanNSArrayto process and the class’ internal logic requires that the stack have elements popped off the array as it is processed. Thus you need to make amutableCopyso that it can be mutated for processing.