是否有可能创建对结构数组元素的引用?
Posted
技术标签:
【中文标题】是否有可能创建对结构数组元素的引用?【英文标题】:Is it ever possible to create a reference to element of array of struct? 【发布时间】:2020-12-08 15:28:45 【问题描述】:给定一个Array
和struct
import Foundation
struct Card
var flag: String = ""
var cards = Array<Card>()
cards.append(Card())
以下操作不会修改原始数组元素
// A copy is created.
var cardCopy = cards[0]
// Will NOT modify cards[0]
cardCopy.flag = "modify0"
print(cards[0].flag)
下面的操作会修改原来的数组元素
// We can modify cards[0] by
cards[0].flag = "modify"
print(cards[0].flag)
但是,从某种意义上说它并不高效,我们每次都需要执行索引访问。想象一下
cards[0].flag0 = "modify"
cards[0].flag1 = "modify"
cards[0].flag2 = "modify"
cards[0].flag3 = "modify"
...
有没有办法,我们可以创建对结构数组元素的引用?这样我们就可以编写
// How to create a reference to cards[0]?
var cardReference = ...
cardReference.flag0 = "modify"
cardReference.flag1 = "modify"
cardReference.flag2 = "modify"
cardReference.flag3 = "modify"
...
其中一种可能性是将struct
替换为class
。但是,在此之前,我想探索其他替代方案。
【问题讨论】:
如果你需要修改你的 Card 实例很多,也许你应该把它变成一个类,或者用新值创建一个新实例并替换数组中的整个对象。 @JoakimDanielson 谢谢。在将其从结构转换为类之前,我想探索其他可能的替代方案(可能创建引用?)。 您不能将值类型转换为引用类型。正如其他人指出的那样,inout
与您将要获得的一样接近。
【参考方案1】:
您可以使用函数进行更改并通过引用传递Card
结构,如下所示:
func update(card: inout Card)
card.flag0 = "modify"
card.flag1 = "modify"
card.flag2 = "modify"
card.flag3 = "modify"
var cards = Array<Card>()
cards.append(Card())
update(card: &cards[0])
甚至更好的是在Card
类型中使用变异函数并将您的更改作为闭包传递:
struct Card
var flag0: String = ""
var flag1: String = ""
var flag2: String = ""
var flag3: String = ""
mutating func update(block: (inout Card) -> Void)
block(&self)
var cards = Array<Card>()
cards.append(Card())
cards[0].update
$0.flag0 = "modify"
$0.flag1 = "modify"
$0.flag2 = "modify"
$0.flag3 = "modify"
更新:为了使第二种方法更加可重用,您可以定义如下协议:
protocol Updatable
mutating func update(block: (inout Self) -> Void)
extension Updatable
mutating func update(block: (inout Self) -> Void)
block(&self)
并使 Card
结构符合它:
struct Card: Updatable
var flag0: String = ""
var flag1: String = ""
var flag2: String = ""
var flag3: String = ""
那么你就可以像上面一样使用它了。
【讨论】:
我真的很喜欢这种使结构通常可以自我更新的技巧;我不敢相信我从来没有想过这个。 :) 我想把这个想法写进我的书中(当然归功于你);如果可以,请告诉我。 @matt 我做了一些研究,关于我第一次看到这样的东西并发现这个gist.github.com/nicklockwood/9b4aac87e7f88c80e932ba3c843252df。所以,对我来说这当然没问题,但公平地说,这并不完全是我的想法。 好吧,你的想法并不是真正取自那个要点,所以我仍然认为你得到了信任。 @matt 好吧,是的,这就像相同技术的另一种用法。【参考方案2】:这是预期的行为,因为Array
是struct
而struct
s 是值类型。
您需要的是引用类型行为,因此您应该将您的 struct
转换为 class
。
一次性修改值类型的多个属性的另一种解决方案是创建一个 mutating
函数来执行此操作并在数组元素上调用它。
struct Card
var flag: String = ""
var flag2 = ""
mutating func update(flag: String, flag2: String)
self.flag = flag
self.flag2 = flag2
var cards = [Card(flag: "a", flag2: "b")]
cards[0].update(flag: "b", flag2: "c")
【讨论】:
以上是关于是否有可能创建对结构数组元素的引用?的主要内容,如果未能解决你的问题,请参考以下文章