这是来自加法计算器的代码,通过首先输入两个操作数然后输入操作来执行操作;像“5输入2输入+”将导致“7”。当用户点按某个号码时,double
将被发送到pushOperand:
当用户点按添加按钮时,字符@"+"
将被发送到performOperation:
。我的问题是,如果这些副本都是浅层副本,那么在program
和runProgram:
制作这些副本的重点是什么,它们的元素最终都指向NSNumber
和{{NSString
1}}对象为_programStack
,program
和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
答案 0 :(得分:0)
NSNumber
和NSString
是不可变的,因此制作一个无法改变的对象集合的浅表副本是安全的。
在program
中,重要的是返回programStack
的副本而不是实际的可变数组。这是因为programStack
是在类扩展中声明的私有内部属性,因此它不是外部可见的。如果您直接返回programStack
,则外部用户可以更改NSMutableArray
,因为它是program
。 NSArray
方法返回programStack
,因为可变对象的副本是不可变的,具有正确的语义。您希望为外部用户提供runProgram
数组的快照,而不是访问您的类内部。
在CalculatorBrain
中,情况有所不同。外部用户将NSArray
和mutableCopy
传递给进程,并且类的内部逻辑要求堆栈在处理时从阵列中弹出元素。因此,您需要创建一个{{1}},以便可以对其进行变异处理。