0

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
4

2 回答 2

1

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

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

正如NSMutableCopying文档(方法从何而来mutableCopy)所说,

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

如果您希望自己的类有这种区别,最好的方法是在/或/的模具中创建两个类,其中可变版本是另一个的子类。所以你可能有和。NSArrayNSMutableArrayNSStringNSMutableStringFractionMutableFraction

只会MutableFraction有方法set:over:Fraction实例将要求在创建对象时设置这些值。然后,您将实现mutableCopyinFraction以返回一个实例MutableFraction(您的实现copy可以保持原样)。

于 2012-08-08T00:23:31.503 回答
1

因为你的类是可变的。Objective-C 不知道你的意思是它是不可变的——该语言甚至不知道不可变的含义。如果你的类有变异器(导致其状态或值改变的方法),NSCopying不会让它们消失。

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

于 2012-08-08T00:24:14.813 回答