使用copyWithZone的不可变对象:

时间:2012-08-08 00:17:44

标签: objective-c copy

我想知道为什么当它引用由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

2 个答案:

答案 0 :(得分:1)

可变性由类定义,而不是由用于创建实例的方法定义,而不是由框架定义,当然也不是由语言定义。只有您自己的代码才能使您的类不可变。

更简单地说,如果类为某些属性提供了setter方法,那么无论您使用copy还是mutableCopy,都可以设置该属性。

正如NSMutableCopying docsmutableCopy方法出现的那样)说,

  

只有定义“不可变与可变”区别的类才应采用此协议。

如果您希望对自己的班级进行区分,最好的方法是在NSArray / NSMutableArray或{{1}模具中制作两个类} / NSString,其中可变版本是另一个的子类。因此,您可能拥有NSMutableStringFraction

只有MutableFraction才能使用方法MutableFraction; set:over:个实例需要在创建对象时设置这些值。然后,您将在Fraction中实施mutableCopy以返回Fraction的实例(MutableFraction的实现可以保持原样)。

答案 1 :(得分:1)

因为你的班级是可变的。 Objective-C并不知道你的意思是它是不可变的 - 语言甚至不知道不变性意味着什么。如果你的类有mutators(导致其状态或值改变的方法),NSCopying将不会让它们消失。

如果您希望您的类真正不可变,请删除您的mutator(-set:over:。)如果您想区分可变对象和不可变对象,请创建一个MutableFraction子类并公开-set:over:只在那个子类中。