返回副本还是可变对象

3
哪种变体更正确?
//first variant
    - (NSArray*) someArray
    {
     NSMutableArray* mutArr = [[NSMutableArray alloc] init];

     //...some operations with mutArr


     NSArray* retArray = [mutArr copy];

     [mutArr release]; //remove mutArr

     return [retArray autorelease];
    }

//second variant
    - (NSArray*) someArray
    {
     NSMutableArray* mutArr = [[NSMutableArray alloc] init];

     //...some operations with mutArr 

     return (NSArray*)[mutArr autorelease];
    }
3个回答

6
答案是,如果你返回的数组在返回后更改了,会有多大的问题?
如果你在方法内部创建一个可变数组然后返回它,并且不再使用它,那么我认为返回可变版本是可以的。你的方法声明返回类型为NSArray仅意味着你不能保证该数组是可变的。你不必保证它是不可变的。
另一方面,如果你返回的数组是你的类在内部使用的,则更安全的方法是返回一个不可变的副本。在你上面的例子中,这似乎并不是这种情况。
数组的使用者,如果想要保留引用,应该使用`copy`而不是`retain`;如果数组是可变的,他们将获得一个不可变的副本。如果它已经是不可变的,只会增加引用计数。因此,复制不可变对象没有任何代价。
换句话说,你的第二个变量是可以的。(尽管将其转换为`(NSArray *)`是完全没有必要的。)

1

我假设你的意思是让mutArrnames成为同一个数组。如果是这样的话,那么第一种方法更正确,因为你不需要真正复制它。

如果你想要的话,可以直接返回mutArray;由于NSMutableArrayNSArray的子类,返回一个将会起作用。如果你想要返回一个常规的、非可变的NSArray,我建议使用以下方法:

(NSArray*)someArray {
    NSMutableArray* mutArr = [[[NSMutableArray alloc] init ] autorelease];
    // your operations here
    return [NSArray arrayWithArray:mutArr];
}

3
在返回之前,请不要忘记释放 mutArr,或者至少将其添加到 autorelease 池中。 - dreamlax
当然可以。这是我的错误。mutAttr和names是同一个数组。我已经修复了它。 - user120084

1

在我看来,第一个更好。它确保了不可变性。


但是在这种情况下确保不可变性很重要吗?由于所讨论的数组是一个临时工作变量,为什么要费心制作副本呢? - benzado
我们不知道数组将去何方或如何处理它。即使返回类型指示“NSArray”。例如,对象序列化程序遵循对象的实际类,而不是您告诉编译器的变量类型。 - dreamlax
这取决于序列化器; Cocoa的NSKeyedArchiver将所有数组存储为不可变类型。如果您归档了一个可变数组,解档时会得到一个不可变数组。如果需要可变数组,您需要在initWithCoder:中调用mutableCopy方法。 - benzado

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接