是否可以仅使用常量属性在两个结构之间实现双向关系?

Is it possible to implement a bidirectional relationship between two structs using only constant properties?

我的用例基于以下模型:

struct Person {
  let name: String
  let houses: [House]
}

struct House {
  let owner: Person
}

现在,理想情况下,我想保持一种双向关系,要求每栋房子都只有一个所有者,而所有者也应该知道所有房子。

使用上面的数据结构,是否可以创建 HousePerson 的实例,使得两者之间存在关系,并且对象本质上是相互指向对方的?

我想这个措辞已经有点误导了,因为由于 structs 的值语义,它们实际上并不指向任何地方,而只是保存值的副本。显然不可能创建具有双向关系的这两个对象,但我仍然想确定并在这里提出这个问题!

一个明显的解决方案也是在声明它们时使用 var 而不是 let 来创建 housesowner 变量,然后可以在每个 struct:

的初始值设定项
struct Person {
  let name: String
  var houses: [House]

  init(name: String, houses: [House]) {
    self.name = name
    self.houses = houses
    self.houses = houses.map { (house: House) in
      var newHouse = house
      newHouse.owner = self
      return newHouse
    }
  }
}


struct House {
  var owner: Person

  init(owner: Person) {
    self.owner = owner
    var newHouses = self.owner.houses
    newHouses.append(self)
    self.owner = Person(name: owner.name, houses: newHouses)
  }
}   

但是,如果我想保持 housesowner 不变怎么办?正如我所说,这似乎很明显是不可能的,但我想知道是否有一些奇特的(可能是功能性的)方法可以实现这一目标?我在想 lenses,在处理不可变模型时可以用作 getterssetters

您所描述的听起来更像是 ORM 而不是语言功能,而且听起来也不适合处理结构等值类型。您如何期望语言知道 ownerhouses 的反向关系 属性 并且需要相应地维护?这是需要用代码强制执行的事情,而单独使用 Swift 语言是不可能的。

听起来您正在尝试维护某种模型对象图,这是一个已经解决了很多次的问题。您应该看看 Realm DB and Core Data,它们都提供托管双向关系。然而,您会发现这些都不是用结构实现的。使用值类型的问题在于它们是写时复制的。一旦你改变了对象图中的一个结构,你就需要将它的所有相关事物重新分配给新的、变异的副本,然后它又发生变异并且需要更新所有 它们的 相关结构。引用语义 (类) 使维护对象图变得更加容易,因为突变不会产生新实例。

使用结构无法实现您想要的。您当前的解决方案(var)并不像您认为的那样工作:所有值都是独立的副本。考虑以下示例:

let p = Person(name: "Nick", houses: [])
let h = House(owner: p)
h.owner.houses
p.houses

因为每个副本都是独立的,这意味着 ph.owner 不同。

如果需要双向关系,则应使用带有 weak 指针的对象(以打破引用循环)。或者,您可以考虑看看是否需要双向关系。