1

在 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

4 回答 4

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;
}

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

于 2013-01-30T00:30:43.713 回答
2

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

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

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

于 2013-01-29T22:42:05.980 回答
0

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

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

考虑这样的属性:

@property (nonatomic,assign) NSSet* set;

类客户端可以这样做:

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

一旦改变了集合,它可能会使类处于不一致的状态。

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

于 2013-01-30T11:28:28.693 回答
0

不,这是一种绝对正确的 OOP 方法(它利用了多态性)。每一个NSMutableSet都是适当的NSSet。不要过度复制。

于 2013-01-29T22:36:20.750 回答