在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;
}
}
答案 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。