+ (NSArray *)arrayOfSomething { NSMutableArray *array = [NSMutableArray array]; // Add objects to the array return [[array copy] autorelease]; }
我的问题是关于这个方法的最后一行:返回可变对象并避免复制操作或返回不可变副本是否更好?是否有任何充分的理由避免返回一个不可预期的可变对象?
(我知道返回NSMutableArray是合法的,因为它是NSArray的子类.我的问题是这是否是一个好主意.)
解决方法
关于使用内省来确定返回对象的可变性,Apple有这个说法:
To determine whether it can change a received object,the receiver must rely on the formal type of the return value. If it receives,for instance,an array object typed as immutable,it should not attempt to mutate it. It is not an acceptable programming practice to determine if an object is mutable based on its class membership
(我的重点)
本文接着给出了几个很好的理由,说明为什么你不应该对返回的对象使用内省来确定你是否可以改变它,例如
You read a property list from a file. When the Foundation framework processes the list it notices that varIoUs subsets of the property list are identical,so it creates a set of objects that it shares among all those subsets. Afterwards you look at the created property list objects and decide to mutate one subset. Suddenly,and without being aware of it,you’ve changed the tree in multiple places.
和
You ask NSView for its subviews (subviews method) and it returns an object that is declared to be an NSArray but which could be an NSMutableArray internally. Then you pass that array to some other code that,through introspection,determines it to be mutable and changes it. By changing this array,the code is mutating NSView’s internal data structures.
鉴于上述情况,你可以完全接受在你的例子中返回可变数组(前提是,在返回之后你永远不会自己改变它,因为那样你就会违反合同).
话虽如此,几乎没有人读过Cocoa Objects Guide的那一部分,所以防御性编程会要求你制作一个不可变的副本并返回,除非性能分析表明这是一个问题.