2012-08-08 77 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: