2012-08-08 73 views
0

我想知道为什么我仍然允许在参照NSCopyWithZone:制作的不可变Fraction对象时允许更改fracB带有copyWithZone的不可变对象:

#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 

回答

1

的可变性是由类定义,而不是由所使用不是由框架来创建实例中,该方法,当然由语言不。只有你自己的代码可以导致你的类不可变。

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

由于NSMutableCopying docs(是从何而来的mutableCopy方法)说,

只有定义“不可改变的与可变”的区别应该采用这种协议班。

如果你想这个区别对于自己的类,最好的办法是使2个班,在NSArray/NSMutableArrayNSString/NSMutableString,模具,其中可变版本是其他的子类。所以你可能有FractionMutableFraction

只有MutableFraction将有方法set:over:; Fraction实例需要在创建对象时设置这些值。然后,您将在Fraction中实施mutableCopy以返回MutableFraction的实例(您的copy的实施可保持不变)。

1

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

如果你想你的类是真正的不可变的,免除您的突变(-set:over:。)如果你想可变和不可变对象之间的区别,创建一个MutableFraction子类,并仅在该子类中暴露-set:over: