我的用例基于以下模型:
struct Person {
let name: String
let houses: [House]
}
struct House {
let owner: Person
}
现在,理想情况下,我希望保持一种双向关系,要求每个房子只有一个所有者,而房主也应该知道所有房屋。
使用上述数据结构,是否可以创建House
和Person
的实例,以便两者之间存在关系,并且对象基本上彼此指向?
我猜这个措辞已经有些误导了,因为struct
s的价值语义,它们并不是真正指向任何地方,而只是持有价值的副本。似乎很明显,用双向关系创建这两个对象是不可能的,但我仍然想确定并在这里提出这个问题!
一个明显的解决方案也是在声明它们时使用houses
而不是owner
制作var
和let
变量,然后可以在初始值设定项中维护关系每个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)
}
}
但是,如果我想让houses
和owner
保持不变怎么办?正如我所说,似乎很明显它是不可能的,但我想知道是否有一些花哨的(可能是功能性的)方法来达到这个目的?我在考虑lenses,在处理不可变模型时可以用作 getters 和 setters 。
答案 0 :(得分:4)
你所描述的内容听起来更像是一个ORM,而不是一个语言特征,并且听起来也不适合处理像结构这样的值类型。您如何期望该语言知道owner
是houses
的反向关系属性并且需要相应地进行维护?只需使用Swift语言就无法使用代码强制执行此操作。
听起来你正在尝试维护某种模型对象图,这是一个已经多次解决的问题。您应该查看Realm DB和Core Data,它们都提供托管双向关系。但是,您会发现这些都不是使用结构实现的。使用值类型的问题在于它们是写时复制。一旦你改变了对象图中的一个结构,你就需要将所有相关的东西重新分配给新的变异副本,然后反过来变异并且需要更新所有< em>他们的相关结构。引用语义(类)使得维护对象图更加容易,因为突变不会产生新的实例。
答案 1 :(得分:3)
你想要什么是不可能使用结构。您当前的解决方案(使用var
)不会像您认为的那样工作:所有值都是独立的副本。请考虑以下示例:
let p = Person(name: "Nick", houses: [])
let h = House(owner: p)
h.owner.houses
p.houses
由于每个副本都是独立的,这意味着p
与h.owner
不同。
如果需要双向关系,则应使用带有weak
指针的对象(以打破参考周期)。或者,您可以考虑是否需要双向关系。