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

廉价感情. 提交于 2019-12-11 10:56:54

问题


In objective-C I find myself creating alot of Mutable objects and then returning them as non mutable objects. Is the way I am doing it here, simply returning the NSMutableSet as an NSSet a good practice? 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;
    }
}

回答1:


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.




回答2:


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.

Certainly, if you're creating a public API, I'd recommend returning a copy. 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. So I would say its good practice to default to.




回答3:


No. This is an absolutely correct OOP approach (it takes advantage of polymorphism). Every NSMutableSet is a proper NSSet. Don't copy superfluously.




回答4:


Not a full answer here, consider NSProxy's one, but I want to clarify something.

In your case you create your object from scratch, and you don't set any ivar to point to that object. 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.



来源:https://stackoverflow.com/questions/14593290/obj-c-using-mutable-and-returning-non-mutable-classes-in-methods

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!