我想知道为什么当它引用由fracB
生成的不可变Fraction
对象时,我仍然可以更改NSCopyWithZone:
?
#import <Foundation/Foundation.h>
@interface Fraction : NSObject <NSCopying>
@property int numerator, denominator;
-(void) set: (int) n over: (int) d;
-(Fraction *) initWithValues: (int) n over: (int) d;
@end
@implementation Fraction
@synthesize numerator, denominator;
-(Fraction *) initWithValues:(int)n over:(int)d {
self = [super init];
if (self)
[self set:n over:d];
return self;
}
-(void) set: (int) n over:(int)d {
numerator = n;
denominator = d;
}
-(Fraction *) copyWithZone:(NSZone *)zone {
Fraction *copied = [[Fraction allocWithZone: zone] init];
[copied set:numerator over:denominator];
return copied;
}
@end
#import "Fraction.h"
#import <Foundation/Foundation.h>
int main (int argc, char *argv[])
{
@autoreleasepool {
Fraction *fracA = [[Fraction alloc] initWithValues:5 over:5];
Fraction *fracB = [[Fraction alloc] init];
fracB = [fracA copy];
[fracB set:2 over:2];
NSLog(@"%@", fracB);
}
return 0;
}
2012-08-07 20:01:04.248 prog[1972:707] 2/2
答案 0 :(得分:1)
可变性由类定义,而不是由用于创建实例的方法定义,而不是由框架定义,当然也不是由语言定义。只有您自己的代码才能使您的类不可变。
更简单地说,如果类为某些属性提供了setter方法,那么无论您使用copy
还是mutableCopy
,都可以设置该属性。
正如NSMutableCopying
docs(mutableCopy
方法出现的那样)说,
只有定义“不可变与可变”区别的类才应采用此协议。
如果您希望对自己的班级进行区分,最好的方法是在NSArray
/ NSMutableArray
或{{1}模具中制作两个类} / NSString
,其中可变版本是另一个的子类。因此,您可能拥有NSMutableString
和Fraction
。
只有MutableFraction
才能使用方法MutableFraction
; set:over:
个实例需要在创建对象时设置这些值。然后,您将在Fraction
中实施mutableCopy
以返回Fraction
的实例(MutableFraction
的实现可以保持原样)。
答案 1 :(得分:1)
因为你的班级是可变的。 Objective-C并不知道你的意思是它是不可变的 - 语言甚至不知道不变性意味着什么。如果你的类有mutators(导致其状态或值改变的方法),NSCopying
将不会让它们消失。
如果您希望您的类真正不可变,请删除您的mutator(-set:over:
。)如果您想区分可变对象和不可变对象,请创建一个MutableFraction
子类并公开-set:over:
只在那个子类中。