简体   繁体   English

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

[英]Obj-C: using mutable and returning non mutable classes in methods

In objective-C I find myself creating alot of Mutable objects and then returning them as non mutable objects. 在objective-C中,我发现自己创建了很多Mutable对象,然后将它们作为不可变对象返回。 Is the way I am doing it here, simply returning the NSMutableSet as an NSSet a good practice? 这是我在这里做的方式,简单地将NSMutableSet作为NSSet返回是一个好习惯吗? I was thinking maybe I should specify that i make a copy of it. 我想也许我应该指明我复制一份。

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

It depends how much safety you require. 这取决于您需要多少安全。 If you return the object as an NSSet it will still be an NSMutableSet, so it could easily be cast back to one and modified. 如果将对象作为NSSet返回,它仍然是一个NSMutableSet,因此可以很容易地将其转换为一个并进行修改。

Certainly, if you're creating a public API, I'd recommend returning a copy. 当然,如果您正在创建公共API,我建议您返回一份副本。 For in internal project, perhaps the method signature already makes the intention clear enough. 对于内部项目,或许方法签名已经足够清楚了。

Its, worth noting that, generally the performance impact of returning a copy is negligible - copying an immutable instance is effectively free whereas each copy sent to a mutable-passing-as-immutable will create another copy. 值得注意的是,通常返回副本的性能影响可以忽略不计 - 复制不可变实例实际上是免费的,而发送到mutable-pass-as-immutable的每个副本将创建另一个副本。 So I would say its good practice to default to. 所以我会说它默认为默认的好习惯。

If I were you, I would do it this way. 如果我是你,我会这样做。

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

I find using predicate to filter array quite comprehensive and easy. 我发现使用谓词来过滤数组非常全面和容易。 Rather than dealing with creating a new mutable type and then testing certain condition, adding until the loop; 而不是处理创建新的可变类型,然后测试某些条件,添加到循环; in this scenario, it seems to be easier to use predicate. 在这种情况下,使用谓词似乎更容易。 Hope this helps you. 希望这对你有所帮助。

No. This is an absolutely correct OOP approach (it takes advantage of polymorphism). 不。这是一种绝对正确的OOP方法(它利用了多态性)。 Every NSMutableSet is a proper NSSet . 每个NSMutableSet都是一个合适的NSSet Don't copy superfluously. 不要多余地复制。

Not a full answer here, consider NSProxy's one, but I want to clarify something. 这里不是一个完整的答案,考虑NSProxy的一个,但我想澄清一些事情。

In your case you create your object from scratch, and you don't set any ivar to point to that object. 在您的情况下,您从头开始创建对象,并且不要将任何ivar设置为指向该对象。 In my opinion in a good percentage of cases you don't need to make a copy of the mutable object returned. 在我看来,在很多情况下你不需要复制返回的可变对象。 But if there is a good reason to deny the class client from mutating the class, then you should copy the variable. 但是如果有充分的理由拒绝类客户端改变类,那么你应该复制变量。

Consider a property like this: 考虑这样的属性:

@property (nonatomic,assign) NSSet* set;

The class client could do this: 类客户端可以这样做:

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

Once mutated the set it could make the class be in an inconsistent state. 一旦变异,它就会使类处于不一致状态。

That's why when I have a property with the type of a class that has also a mutable version, I always put copy instead of assign in the property. 这就是为什么当我有一个类的类型也具有可变版本的属性时,我总是在属性中放置copy而不是assign。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM