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

时间:2016-07-25 01:32:53

标签: ios swift functional-programming immutability lenses

我的用例基于以下模型:

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

struct House {
  let owner: Person
}

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

使用上述数据结构,是否可以创建HousePerson的实例,以便两者之间存在关系,并且对象基本上彼此指向?

我猜这个措辞已经有些误导了,因为struct s的价值语义,它们并不是真正指向任何地方,而只是持有价值的副本。似乎很明显,用双向关系创建这两个对象是不可能的,但我仍然想确定并在这里提出这个问题!

一个明显的解决方案也是在声明它们时使用houses而不是owner制作varlet变量,然后可以在初始值设定项中维护关系每个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,在处理不可变模型时可以用作 getters setters

2 个答案:

答案 0 :(得分:4)

你所描述的内容听起来更像是一个ORM,而不是一个语言特征,并且听起来也不适合处理像结构这样的值类型。您如何期望该语言知道ownerhouses的反向关系属性并且需要相应地进行维护?只需使用Swift语言就无法使用代码强制执行此操作。

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

答案 1 :(得分:3)

你想要什么是不可能使用结构。您当前的解决方案(使用var)不会像您认为的那样工作:所有值都是独立的副本。请考虑以下示例:

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

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

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