Obj-C:在方法中使用mutable和返回非可变类

时间:2013-01-29 22:33:35

标签: objective-c collections nsmutablearray

在objective-C中,我发现自己创建了很多Mutable对象,然后将它们作为不可变对象返回。这是我在这里做的方式,只需将NSMutableSet作为NSSet作为一种良好做法返回?我想也许我应该指明我复制一份。

/**  Returns all the names of the variables used in a given
 *   program. If non are used it returns nil */
+ (NSSet *)variablesUsedInProgram:(id)program
{
    NSMutableSet* variablesUsed = [[NSMutableSet alloc]init];
    if ([program isKindOfClass:[NSArray class]]) {
        for (NSString *str in program)
        {
            if ([str isEqual:@"x"] || [str isEqual:@"y"] || [str isEqual:@"a"] || [str isEqual:@"b"])
                [variablesUsed addObject:str];
        }
    }
    if ([variablesUsed count] > 0) {
        return variablesUsed;
    } else {
        return nil;
    }
}

4 个答案:

答案 0 :(得分:2)

这取决于您需要多少安全性。如果将对象作为NSSet返回,它仍然是一个NSMutableSet,因此可以很容易地将其转换为一个并进行修改。

当然,如果您正在创建公共API,我建议您返回一份副本。对于内部项目,或许方法签名已经足够明确了。

值得注意的是,通常返回副本的性能影响可以忽略不计 - 复制不可变实例实际上是免费的,而发送到mutable-pass-as-immutable的每个副本都会创建另一个副本。所以我会说它默认为默认的好习惯。

答案 1 :(得分:2)

如果我是你,我会这样做。

+ (NSSet *)variablesUsedInProgram:(id)program
{
    NSSet *variablesUsed;
    if ([program isKindOfClass:[NSArray class]]) {
      NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF = 'x' or SELF = 'y' or SELF = 'z'"];
      variablesUsed = [NSSet setWithArray:[program filteredArrayUsingPredicate:predicate]];  
    }
    int count;
    return (count = [variablesUsed count]) > 0 ? variablesUsed : nil;
}

我发现使用谓词过滤数组非常全面和容易。而不是处理创建新的可变类型,然后测试某些条件,添加到循环;在这种情况下,使用谓词似乎更容易。希望这会对你有所帮助。

答案 2 :(得分:0)

没有。这是一种绝对正确的OOP方法(它利用了多态性)。每个NSMutableSet都是合适的NSSet。不要多余地复制。

答案 3 :(得分:0)

这里不是完整的答案,请考虑NSProxy的答案,但我想澄清一些事情。

在您的情况下,您从头开始创建对象,并且不要将任何ivar设置为指向该对象。在我看来,在很多情况下你不需要复制返回的可变对象。但是如果有充分的理由拒绝类客户端改变类,那么你应该复制变量。

考虑这样的属性:

@property (nonatomic,assign) NSSet* set;

班级客户可以这样做:

NSMutableSet* set= ... ; // inizialized to some value
classInstance.set= set;
// Mutate the set

一旦变异,它就会使类处于不一致状态。

这就是为什么当我有一个类的类型也具有可变版本的属性时,我总是在属性中放置copy而不是assign。