Swift 计算属性返回底层数组的副本
Posted
技术标签:
【中文标题】Swift 计算属性返回底层数组的副本【英文标题】:Swift computed property to return copy of underlying array 【发布时间】:2014-09-11 23:40:53 【问题描述】:我有一个用 Objective-C 编写的模型类,我正在将其转换为 Swift。它在内部包含一个NSMutableArray
,但getter 的方法签名以及实际返回值是NSArray
。调用时,它会创建一个不可变副本以返回。
本质上,我希望调用者能够迭代/检查容器,但不能修改它。我有这个测试sn-p:
class Container
internal var myItems = [String]()
func sayHello()
"I have: \(myItems)"
let cont = Container()
cont.myItems.append("Neat") // ["Neat"]
cont.sayHello() // This causes sayHello() to print: "I have: [Neat]"
var isThisACopy = cont.myItems
isThisACopy.append("Huh") // ["Neat", "Huh"]
cont.sayHello() // This ALSO causes sayHello() to print: "I have: [Neat]"
我一直在尝试找到一种方法来覆盖 myItems
的 getter,以便它返回一个不可变的副本,但似乎无法确定如何。
尝试 #1
这会产生编译器错误:Function produces expected type '_ArrayBuffer<(String)>'; did you mean to call it with '()'?
internal var myItems = [String]()
var copy = [String]()
for item in ... // What to use in the ...?
copy.append(item)
return copy
尝试 #2
这也会产生编译器错误,因为我(可以理解)重新定义生成的 getter Invalid redeclaration of 'myItems()'
:
internal func myItems() -> [String]
var copy = [String]()
for item in myItems
copy.append(item)
return copy
【问题讨论】:
【参考方案1】:试试这个:
class Container
private var _myItems: [String] = ["hello"]
internal var myItems: [String]
return _myItems
let cont = Container()
cont.myItems.append("Neat") //not allowed
它使用私有存储属性和返回不可变副本的计算属性。存储属性不能使用自定义 getter。
【讨论】:
这是我在尝试 #1 中遇到的另一个问题:self.myItems
的访问会产生无限递归,因为 getter 正在调用 自身。
我不确定您的实际用例是什么,但您可以使用 internal var myItems: [String] return self.myItems
它返回 myItems 的不可变副本
否 - 这也有同样的问题。使用self.myItems
调用getter,它使用self.myItems
,调用getter... Womp womp。 :-)
你可以添加一个公共计算属性(使用不同的名称)返回该数组的不可变副本吗?
我熟悉下划线方法 - 这会起作用。使用动态吸气剂时没有“直接访问”,有点令人遗憾。我想这不是他们的工作方式。谢谢!【参考方案2】:
expose mutable properties as immutable 的更好方法:
class Container
private (set) internal var myItems: [String]
【讨论】:
您能解释一下编译器如何确定列表本身应该是不可变的吗?我可以理解private(set)
阻止调用者将myItems
指向一个新列表,但我不太明白它是如何知道(没有任何let
出现)该列表也是不可变的?
@CraigOtis 与@connor 的答案中的myItems
相同——只读具有与常量相同的语义。以上是关于Swift 计算属性返回底层数组的副本的主要内容,如果未能解决你的问题,请参考以下文章